[V3,2/2] Add a new warning option -Wstrict-flex-arrays.

Message ID 20221206161844.2397151-1-qing.zhao@oracle.com
State New
Headers
Series Update -Warray-bounds with -fstrict-flex-arrays |

Commit Message

Qing Zhao Dec. 6, 2022, 4:18 p.m. UTC
  '-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.

gcc/ChangeLog:

	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
	arguments.
	(array_bounds_checker::check_array_ref): Issue warnings for
	-Wstrict-flex-arrays.
	* opts.cc (finish_options): Issue warning for unsupported combination
	of -Wstrict_flex_arrays and -fstrict-flex-array.
	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
	warn_strict_flex_array is true.

gcc/c-family/ChangeLog:

	* c.opt (Wstrict-flex-arrays): New option.

gcc/testsuite/ChangeLog:

	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
	-Wstrict-flex-arrays.
	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
---
 gcc/c-family/c.opt                            |   5 +
 gcc/doc/invoke.texi                           |  27 ++++-
 gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
 gcc/opts.cc                                   |   8 ++
 .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
 .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
 .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
 .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
 .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
 .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
 .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
 gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
 gcc/tree-vrp.cc                               |   2 +-
 15 files changed, 273 insertions(+), 34 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
  

Comments

Qing Zhao Dec. 13, 2022, 3:27 p.m. UTC | #1
Richard, 

Do you have any decision on this one? 
Do we need this warning option For GCC? 

thanks.

Qing

> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
> 
> gcc/ChangeLog:
> 
> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
> 	arguments.
> 	(array_bounds_checker::check_array_ref): Issue warnings for
> 	-Wstrict-flex-arrays.
> 	* opts.cc (finish_options): Issue warning for unsupported combination
> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
> 	warn_strict_flex_array is true.
> 
> gcc/c-family/ChangeLog:
> 
> 	* c.opt (Wstrict-flex-arrays): New option.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
> 	-Wstrict-flex-arrays.
> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
> ---
> gcc/c-family/c.opt                            |   5 +
> gcc/doc/invoke.texi                           |  27 ++++-
> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
> gcc/opts.cc                                   |   8 ++
> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
> gcc/tree-vrp.cc                               |   2 +-
> 15 files changed, 273 insertions(+), 34 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
> 
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index 0d0ad0a6374..33edeefd285 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
> index 726392409b6..4402b0427ef 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -398,7 +398,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
> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
> --- a/gcc/gimple-array-bounds.cc
> +++ b/gcc/gimple-array-bounds.cc
> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
> 
> /* 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.
> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
> +   When out of bounds, set OUT_OF_BOUND to true.
> +   Issue warnings if FOR_ARRAY_BOUND is true.
> +   return TRUE if warnings are issued.  */
> +
> 
> 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 ignore_off_by_one, bool for_array_bound,
> +			      bool *out_of_bound)
> {
>   tree low_bound = array_ref_low_bound (ref);
>   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
> 
>   bool warned = false;
> +  *out_of_bound = 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_org, artype);
> +    {
> +      *out_of_bound = true;
> +      if (for_array_bound)
> +	warned = warning_at (location, OPT_Warray_bounds_,
> +			     "array subscript %E is outside array"
> +			     " bounds of %qT", low_sub_org, artype);
> +    }
> 
>   if (warned)
>     ; /* Do nothing.  */
> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
> +	{
> +	  *out_of_bound = true;
> +	  warned = warning_at (location, OPT_Warray_bounds_,
> +			       "array subscript [%E, %E] is outside "
> +			       "array bounds of %qT",
> +			       low_sub, up_sub, artype);
> +	}
>     }
>   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);
> +    {
> +      *out_of_bound = true;
> +      warned = warning_at (location, OPT_Warray_bounds_,
> +			   "array subscript %E is above array bounds of %qT",
> +			   up_sub, artype);
> +    }
>   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);
> +    {
> +      *out_of_bound = true;
> +      warned = warning_at (location, OPT_Warray_bounds_,
> +			   "array subscript %E is below array bounds of %qT",
> +			   low_sub, artype);
> +    }
>   return warned;
> }
> 
> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
> 
>   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);
> +    {
> +      /* 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);
> +    }
> 
>   get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
> 
>   bool warned = false;
> +  bool out_of_bound = false;
> 
>   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>   tree low_sub_org = TREE_OPERAND (ref, 1);
> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>   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);
> +					 ignore_off_by_one, warn_array_bounds,
> +					 &out_of_bound);
> 
> 
>   if (!warned && sam == special_array_member::int_0)
> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
> --- a/gcc/opts.cc
> +++ b/gcc/opts.cc
> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
>       opts->x_profile_flag = 0;
>     }
> 
> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> index d36ba4d86cb..65c9fec43af 100644
> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> @@ -1,6 +1,6 @@
> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> /* { dg-do compile} */
> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
> 
> struct trailing_array_1 {
>     int a;
> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>     struct trailing_array_4 *trailing_flex)
> {
>     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>     trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> index f63206e1948..2b5a895c598 100644
> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> @@ -1,6 +1,6 @@
> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> /* { dg-do compile } */
> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
> 
> struct trailing_array_1 {
>     int a;
> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>     struct trailing_array_4 *trailing_flex)
> {
>     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>     trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> 
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> index e3273714e8b..25b903f2615 100644
> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> @@ -1,6 +1,6 @@
> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> /* { dg-do compile } */
> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
> 
> struct trailing_array_1 {
>     int a;
> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>     struct trailing_array_4 *trailing_flex)
> {
>     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>     trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
> 
> }
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> index cabaea77dc2..5fc500a19ca 100644
> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> @@ -1,6 +1,6 @@
> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> /* { dg-do compile } */
> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
> 
> struct trailing_array_1 {
>     int a;
> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>     struct trailing_array_4 *trailing_flex)
> {
>     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>     trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> index 8b7db6e4f39..30bb4ca8832 100644
> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> @@ -1,6 +1,6 @@
> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> /* { dg-do compile } */
> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
> 
> struct trailing_array_1 {
>     int a;
> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>     struct trailing_array_4 *trailing_flex)
> {
>     normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> 
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> index 035bf481396..e847a44516e 100644
> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> @@ -1,6 +1,6 @@
> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> /* { dg-do compile } */
> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
> 
> struct trailing_array_1 {
>     int a;
> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>     struct trailing_array_4 *trailing_flex)
> {
>     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>     trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> 
> }
> 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..2e241f96208
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
> @@ -0,0 +1,39 @@
> +/* Test -Wstrict-flex-arrays.  */
> +/* { dg-do compile } */
> +/* { 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" } */
> +
> +}
> 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..97eb65ba0a9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
> @@ -0,0 +1,39 @@
> +/* Test -Wstrict-flex-arrays.  */
> +/* { dg-do compile } */
> +/* { 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" } */
> +
> +}
> 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..110fdc72778
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
> @@ -0,0 +1,39 @@
> +/* Test -Wstrict-flex-arrays.  */
> +/* { dg-do compile } */
> +/* { 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" } */
> +
> +}
> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> index 3846dc1d849..e6c6c5a301d 100644
> --- a/gcc/tree-vrp.cc
> +++ b/gcc/tree-vrp.cc
> @@ -1087,7 +1087,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;
> -- 
> 2.31.1
>
  
Richard Biener Dec. 14, 2022, 9:03 a.m. UTC | #2
On Tue, 13 Dec 2022, Qing Zhao wrote:

> Richard, 
> 
> Do you have any decision on this one? 
> Do we need this warning option For GCC? 

Looking at the testcases it seems that the diagnostic amends
-Warray-bounds diagnostics for trailing but not flexible arrays?
Wouldn't it be better to generally diagnose this, so have
-Warray-bounds, with -fstrict-flex-arrays, for

struct X { int a[1]; };
int foo (struct X *p)
{
  return p->a[1];
}

emit

warning: array subscript 1 is above array bounds ...
note: the trailing array is only a flexible array member with 
-fno-strict-flex-arrays

?  Having -Wstrict-flex-arrays=N and N not agree with the
-fstrict-flex-arrays level sounds hardly useful to me but the
information that we ran into a trailing array but didn't consider
it a flex array because of -fstrict-flex-arrays is always a
useful information?

But maybe I misunderstood this new diagnostic?

Thanks,
Richard.


> thanks.
> 
> Qing
> 
> > On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
> > 
> > gcc/ChangeLog:
> > 
> > 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
> > 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
> > 	arguments.
> > 	(array_bounds_checker::check_array_ref): Issue warnings for
> > 	-Wstrict-flex-arrays.
> > 	* opts.cc (finish_options): Issue warning for unsupported combination
> > 	of -Wstrict_flex_arrays and -fstrict-flex-array.
> > 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
> > 	warn_strict_flex_array is true.
> > 
> > gcc/c-family/ChangeLog:
> > 
> > 	* c.opt (Wstrict-flex-arrays): New option.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
> > 	-Wstrict-flex-arrays.
> > 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
> > 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
> > 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
> > 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
> > 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
> > 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
> > ---
> > gcc/c-family/c.opt                            |   5 +
> > gcc/doc/invoke.texi                           |  27 ++++-
> > gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
> > gcc/opts.cc                                   |   8 ++
> > .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
> > .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
> > .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
> > .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
> > .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
> > .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
> > .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
> > gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
> > gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
> > gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
> > gcc/tree-vrp.cc                               |   2 +-
> > 15 files changed, 273 insertions(+), 34 deletions(-)
> > create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
> > 
> > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> > index 0d0ad0a6374..33edeefd285 100644
> > --- a/gcc/c-family/c.opt
> > +++ b/gcc/c-family/c.opt
> > @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
> > index 726392409b6..4402b0427ef 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -398,7 +398,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
> > @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
> > --- a/gcc/gimple-array-bounds.cc
> > +++ b/gcc/gimple-array-bounds.cc
> > @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
> > 
> > /* 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.
> > -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
> > +   When out of bounds, set OUT_OF_BOUND to true.
> > +   Issue warnings if FOR_ARRAY_BOUND is true.
> > +   return TRUE if warnings are issued.  */
> > +
> > 
> > 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 ignore_off_by_one, bool for_array_bound,
> > +			      bool *out_of_bound)
> > {
> >   tree low_bound = array_ref_low_bound (ref);
> >   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
> > 
> >   bool warned = false;
> > +  *out_of_bound = 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_org, artype);
> > +    {
> > +      *out_of_bound = true;
> > +      if (for_array_bound)
> > +	warned = warning_at (location, OPT_Warray_bounds_,
> > +			     "array subscript %E is outside array"
> > +			     " bounds of %qT", low_sub_org, artype);
> > +    }
> > 
> >   if (warned)
> >     ; /* Do nothing.  */
> > @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
> > +	{
> > +	  *out_of_bound = true;
> > +	  warned = warning_at (location, OPT_Warray_bounds_,
> > +			       "array subscript [%E, %E] is outside "
> > +			       "array bounds of %qT",
> > +			       low_sub, up_sub, artype);
> > +	}
> >     }
> >   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);
> > +    {
> > +      *out_of_bound = true;
> > +      warned = warning_at (location, OPT_Warray_bounds_,
> > +			   "array subscript %E is above array bounds of %qT",
> > +			   up_sub, artype);
> > +    }
> >   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);
> > +    {
> > +      *out_of_bound = true;
> > +      warned = warning_at (location, OPT_Warray_bounds_,
> > +			   "array subscript %E is below array bounds of %qT",
> > +			   low_sub, artype);
> > +    }
> >   return warned;
> > }
> > 
> > @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
> > 
> >   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);
> > +    {
> > +      /* 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);
> > +    }
> > 
> >   get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
> > 
> >   bool warned = false;
> > +  bool out_of_bound = false;
> > 
> >   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
> >   tree low_sub_org = TREE_OPERAND (ref, 1);
> > @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
> >   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);
> > +					 ignore_off_by_one, warn_array_bounds,
> > +					 &out_of_bound);
> > 
> > 
> >   if (!warned && sam == special_array_member::int_0)
> > @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
> > --- a/gcc/opts.cc
> > +++ b/gcc/opts.cc
> > @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
> >       opts->x_profile_flag = 0;
> >     }
> > 
> > +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> > index d36ba4d86cb..65c9fec43af 100644
> > --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> > +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> > @@ -1,6 +1,6 @@
> > -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> > +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> > /* { dg-do compile} */
> > -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
> > +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
> > 
> > struct trailing_array_1 {
> >     int a;
> > @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
> >     struct trailing_array_4 *trailing_flex)
> > {
> >     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> > +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >     trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
> >     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> > diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> > index f63206e1948..2b5a895c598 100644
> > --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> > +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> > @@ -1,6 +1,6 @@
> > -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> > +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> > /* { dg-do compile } */
> > -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
> > +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
> > 
> > struct trailing_array_1 {
> >     int a;
> > @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
> >     struct trailing_array_4 *trailing_flex)
> > {
> >     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> > +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >     trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
> > +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> > 
> > diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> > index e3273714e8b..25b903f2615 100644
> > --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> > +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> > @@ -1,6 +1,6 @@
> > -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> > +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> > /* { dg-do compile } */
> > -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
> > +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
> > 
> > struct trailing_array_1 {
> >     int a;
> > @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
> >     struct trailing_array_4 *trailing_flex)
> > {
> >     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
> > +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
> > +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >     trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
> > +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
> >     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
> > 
> > }
> > diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> > index cabaea77dc2..5fc500a19ca 100644
> > --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> > +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> > @@ -1,6 +1,6 @@
> > -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> > +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> > /* { dg-do compile } */
> > -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
> > +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
> > 
> > struct trailing_array_1 {
> >     int a;
> > @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
> >     struct trailing_array_4 *trailing_flex)
> > {
> >     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> > +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >     trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
> >     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> > diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> > index 8b7db6e4f39..30bb4ca8832 100644
> > --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> > +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> > @@ -1,6 +1,6 @@
> > -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> > +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> > /* { dg-do compile } */
> > -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
> > +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
> > 
> > struct trailing_array_1 {
> >     int a;
> > @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
> >     struct trailing_array_4 *trailing_flex)
> > {
> >     normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
> > +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
> > +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> > 
> > diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> > index 035bf481396..e847a44516e 100644
> > --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> > +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> > @@ -1,6 +1,6 @@
> > -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> > +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> > /* { dg-do compile } */
> > -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
> > +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
> > 
> > struct trailing_array_1 {
> >     int a;
> > @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
> >     struct trailing_array_4 *trailing_flex)
> > {
> >     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
> > +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
> > +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >     trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
> > +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
> >     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> > 
> > }
> > 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..2e241f96208
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
> > @@ -0,0 +1,39 @@
> > +/* Test -Wstrict-flex-arrays.  */
> > +/* { dg-do compile } */
> > +/* { 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" } */
> > +
> > +}
> > 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..97eb65ba0a9
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
> > @@ -0,0 +1,39 @@
> > +/* Test -Wstrict-flex-arrays.  */
> > +/* { dg-do compile } */
> > +/* { 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" } */
> > +
> > +}
> > 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..110fdc72778
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
> > @@ -0,0 +1,39 @@
> > +/* Test -Wstrict-flex-arrays.  */
> > +/* { dg-do compile } */
> > +/* { 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" } */
> > +
> > +}
> > diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> > index 3846dc1d849..e6c6c5a301d 100644
> > --- a/gcc/tree-vrp.cc
> > +++ b/gcc/tree-vrp.cc
> > @@ -1087,7 +1087,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;
> > -- 
> > 2.31.1
> > 
> 
>
  
Qing Zhao Dec. 14, 2022, 2:08 p.m. UTC | #3
> On Dec 14, 2022, at 4:03 AM, Richard Biener <rguenther@suse.de> wrote:
> 
> On Tue, 13 Dec 2022, Qing Zhao wrote:
> 
>> Richard, 
>> 
>> Do you have any decision on this one? 
>> Do we need this warning option For GCC? 
> 
> Looking at the testcases it seems that the diagnostic amends
> -Warray-bounds diagnostics for trailing but not flexible arrays?

Yes.

> Wouldn't it be better to generally diagnose this, so have
> -Warray-bounds, with -fstrict-flex-arrays, for
> 
> struct X { int a[1]; };
> int foo (struct X *p)
> {
>  return p->a[1];
> }
> 
> emit
> 
> warning: array subscript 1 is above array bounds ...
> note: the trailing array is only a flexible array member with 
> -fno-strict-flex-arrays

This is good too.
My only concern with doing this is, the default warning messages of -Warray-bounds would be different than
the current ones, will this have any impact on the current users?

> 
> ?  Having -Wstrict-flex-arrays=N and N not agree with the
> -fstrict-flex-arrays level sounds hardly useful to me but the
> information that we ran into a trailing array but didn't consider
> it a flex array because of -fstrict-flex-arrays is always a
> useful information?

-Wstrict-flex-arrays does NOT have the argument “N”.  Its level will be consistent with the level “N” of the corresponding
-fstrict-flex-array=N.  
-Wstrict-flex-arrays option is only valid when -fstrict-flex-arrays is present, it will report any misuse of treating trailing array 
as flexible array at the LEVEL of -fstrict-flex-arrays. 

Let me know if it is still not very clear.

thanks.

Qing
> 
> But maybe I misunderstood this new diagnostic?
> 
> Thanks,
> Richard.
> 
> 
>> thanks.
>> 
>> Qing
>> 
>>> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
>>> 
>>> gcc/ChangeLog:
>>> 
>>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
>>> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
>>> 	arguments.
>>> 	(array_bounds_checker::check_array_ref): Issue warnings for
>>> 	-Wstrict-flex-arrays.
>>> 	* opts.cc (finish_options): Issue warning for unsupported combination
>>> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
>>> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
>>> 	warn_strict_flex_array is true.
>>> 
>>> gcc/c-family/ChangeLog:
>>> 
>>> 	* c.opt (Wstrict-flex-arrays): New option.
>>> 
>>> gcc/testsuite/ChangeLog:
>>> 
>>> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
>>> 	-Wstrict-flex-arrays.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
>>> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
>>> ---
>>> gcc/c-family/c.opt                            |   5 +
>>> gcc/doc/invoke.texi                           |  27 ++++-
>>> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
>>> gcc/opts.cc                                   |   8 ++
>>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
>>> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
>>> gcc/tree-vrp.cc                               |   2 +-
>>> 15 files changed, 273 insertions(+), 34 deletions(-)
>>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
>>> 
>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>> index 0d0ad0a6374..33edeefd285 100644
>>> --- a/gcc/c-family/c.opt
>>> +++ b/gcc/c-family/c.opt
>>> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
>>> index 726392409b6..4402b0427ef 100644
>>> --- a/gcc/doc/invoke.texi
>>> +++ b/gcc/doc/invoke.texi
>>> @@ -398,7 +398,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
>>> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
>>> --- a/gcc/gimple-array-bounds.cc
>>> +++ b/gcc/gimple-array-bounds.cc
>>> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
>>> 
>>> /* 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.
>>> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
>>> +   When out of bounds, set OUT_OF_BOUND to true.
>>> +   Issue warnings if FOR_ARRAY_BOUND is true.
>>> +   return TRUE if warnings are issued.  */
>>> +
>>> 
>>> 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 ignore_off_by_one, bool for_array_bound,
>>> +			      bool *out_of_bound)
>>> {
>>>  tree low_bound = array_ref_low_bound (ref);
>>>  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>> 
>>>  bool warned = false;
>>> +  *out_of_bound = 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_org, artype);
>>> +    {
>>> +      *out_of_bound = true;
>>> +      if (for_array_bound)
>>> +	warned = warning_at (location, OPT_Warray_bounds_,
>>> +			     "array subscript %E is outside array"
>>> +			     " bounds of %qT", low_sub_org, artype);
>>> +    }
>>> 
>>>  if (warned)
>>>    ; /* Do nothing.  */
>>> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
>>> +	{
>>> +	  *out_of_bound = true;
>>> +	  warned = warning_at (location, OPT_Warray_bounds_,
>>> +			       "array subscript [%E, %E] is outside "
>>> +			       "array bounds of %qT",
>>> +			       low_sub, up_sub, artype);
>>> +	}
>>>    }
>>>  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);
>>> +    {
>>> +      *out_of_bound = true;
>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>> +			   "array subscript %E is above array bounds of %qT",
>>> +			   up_sub, artype);
>>> +    }
>>>  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);
>>> +    {
>>> +      *out_of_bound = true;
>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>> +			   "array subscript %E is below array bounds of %qT",
>>> +			   low_sub, artype);
>>> +    }
>>>  return warned;
>>> }
>>> 
>>> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>> 
>>>  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);
>>> +    {
>>> +      /* 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);
>>> +    }
>>> 
>>>  get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
>>> 
>>>  bool warned = false;
>>> +  bool out_of_bound = false;
>>> 
>>>  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>  tree low_sub_org = TREE_OPERAND (ref, 1);
>>> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>  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);
>>> +					 ignore_off_by_one, warn_array_bounds,
>>> +					 &out_of_bound);
>>> 
>>> 
>>>  if (!warned && sam == special_array_member::int_0)
>>> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
>>> --- a/gcc/opts.cc
>>> +++ b/gcc/opts.cc
>>> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
>>>      opts->x_profile_flag = 0;
>>>    }
>>> 
>>> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>> index d36ba4d86cb..65c9fec43af 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile} */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>> index f63206e1948..2b5a895c598 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> 
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>> index e3273714e8b..25b903f2615 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>    trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
>>> 
>>> }
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>> index cabaea77dc2..5fc500a19ca 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>> index 8b7db6e4f39..30bb4ca8832 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> 
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>> index 035bf481396..e847a44516e 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>    trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> 
>>> }
>>> 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..2e241f96208
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>>> @@ -0,0 +1,39 @@
>>> +/* Test -Wstrict-flex-arrays.  */
>>> +/* { dg-do compile } */
>>> +/* { 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" } */
>>> +
>>> +}
>>> 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..97eb65ba0a9
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>>> @@ -0,0 +1,39 @@
>>> +/* Test -Wstrict-flex-arrays.  */
>>> +/* { dg-do compile } */
>>> +/* { 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" } */
>>> +
>>> +}
>>> 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..110fdc72778
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>>> @@ -0,0 +1,39 @@
>>> +/* Test -Wstrict-flex-arrays.  */
>>> +/* { dg-do compile } */
>>> +/* { 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" } */
>>> +
>>> +}
>>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
>>> index 3846dc1d849..e6c6c5a301d 100644
>>> --- a/gcc/tree-vrp.cc
>>> +++ b/gcc/tree-vrp.cc
>>> @@ -1087,7 +1087,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;
>>> -- 
>>> 2.31.1
>>> 
>> 
>> 
> 
> -- 
> 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)
  
Qing Zhao Dec. 14, 2022, 2:49 p.m. UTC | #4
> On Dec 14, 2022, at 9:08 AM, Qing Zhao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> 
> 
> 
>> On Dec 14, 2022, at 4:03 AM, Richard Biener <rguenther@suse.de> wrote:
>> 
>> On Tue, 13 Dec 2022, Qing Zhao wrote:
>> 
>>> Richard, 
>>> 
>>> Do you have any decision on this one? 
>>> Do we need this warning option For GCC? 
>> 
>> Looking at the testcases it seems that the diagnostic amends
>> -Warray-bounds diagnostics for trailing but not flexible arrays?
> 
> Yes.
> 
>> Wouldn't it be better to generally diagnose this, so have
>> -Warray-bounds, with -fstrict-flex-arrays, for
>> 
>> struct X { int a[1]; };
>> int foo (struct X *p)
>> {
>> return p->a[1];
>> }
>> 
>> emit
>> 
>> warning: array subscript 1 is above array bounds ...
>> note: the trailing array is only a flexible array member with 
>> -fno-strict-flex-arrays
> 
> This is good too.
> My only concern with doing this is, the default warning messages of -Warray-bounds would be different than
> the current ones, will this have any impact on the current users?

My bad, the default warning message of -Warray-bounds without -fstrict-flex-arrays should not be changed.
Only when -fstrict-flex-arrays=N (N>0), the warning messages of -Warray-bounds will be different than the current one.
This should be fine.
> 
>> 
>> ?  Having -Wstrict-flex-arrays=N and N not agree with the
>> -fstrict-flex-arrays level sounds hardly useful to me but the
>> information that we ran into a trailing array but didn't consider
>> it a flex array because of -fstrict-flex-arrays is always a
>> useful information?
> 
> -Wstrict-flex-arrays does NOT have the argument “N”.  Its level will be consistent with the level “N” of the corresponding
> -fstrict-flex-array=N.  
> -Wstrict-flex-arrays option is only valid when -fstrict-flex-arrays is present, it will report any misuse of treating trailing array 
> as flexible array at the LEVEL of -fstrict-flex-arrays. 
> 
> Let me know if it is still not very clear.
> 
> thanks.
> 
> Qing
>> 
>> But maybe I misunderstood this new diagnostic?
>> 
>> Thanks,
>> Richard.
>> 
>> 
>>> thanks.
>>> 
>>> Qing
>>> 
>>>> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
>>>> 
>>>> gcc/ChangeLog:
>>>> 
>>>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
>>>> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
>>>> 	arguments.
>>>> 	(array_bounds_checker::check_array_ref): Issue warnings for
>>>> 	-Wstrict-flex-arrays.
>>>> 	* opts.cc (finish_options): Issue warning for unsupported combination
>>>> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
>>>> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
>>>> 	warn_strict_flex_array is true.
>>>> 
>>>> gcc/c-family/ChangeLog:
>>>> 
>>>> 	* c.opt (Wstrict-flex-arrays): New option.
>>>> 
>>>> gcc/testsuite/ChangeLog:
>>>> 
>>>> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
>>>> 	-Wstrict-flex-arrays.
>>>> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
>>>> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
>>>> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
>>>> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
>>>> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
>>>> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
>>>> ---
>>>> gcc/c-family/c.opt                            |   5 +
>>>> gcc/doc/invoke.texi                           |  27 ++++-
>>>> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
>>>> gcc/opts.cc                                   |   8 ++
>>>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
>>>> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
>>>> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
>>>> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
>>>> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
>>>> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
>>>> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
>>>> gcc/tree-vrp.cc                               |   2 +-
>>>> 15 files changed, 273 insertions(+), 34 deletions(-)
>>>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
>>>> 
>>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>>> index 0d0ad0a6374..33edeefd285 100644
>>>> --- a/gcc/c-family/c.opt
>>>> +++ b/gcc/c-family/c.opt
>>>> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
>>>> index 726392409b6..4402b0427ef 100644
>>>> --- a/gcc/doc/invoke.texi
>>>> +++ b/gcc/doc/invoke.texi
>>>> @@ -398,7 +398,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
>>>> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
>>>> --- a/gcc/gimple-array-bounds.cc
>>>> +++ b/gcc/gimple-array-bounds.cc
>>>> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
>>>> 
>>>> /* 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.
>>>> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
>>>> +   When out of bounds, set OUT_OF_BOUND to true.
>>>> +   Issue warnings if FOR_ARRAY_BOUND is true.
>>>> +   return TRUE if warnings are issued.  */
>>>> +
>>>> 
>>>> 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 ignore_off_by_one, bool for_array_bound,
>>>> +			      bool *out_of_bound)
>>>> {
>>>> tree low_bound = array_ref_low_bound (ref);
>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>> 
>>>> bool warned = false;
>>>> +  *out_of_bound = 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_org, artype);
>>>> +    {
>>>> +      *out_of_bound = true;
>>>> +      if (for_array_bound)
>>>> +	warned = warning_at (location, OPT_Warray_bounds_,
>>>> +			     "array subscript %E is outside array"
>>>> +			     " bounds of %qT", low_sub_org, artype);
>>>> +    }
>>>> 
>>>> if (warned)
>>>>   ; /* Do nothing.  */
>>>> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
>>>> +	{
>>>> +	  *out_of_bound = true;
>>>> +	  warned = warning_at (location, OPT_Warray_bounds_,
>>>> +			       "array subscript [%E, %E] is outside "
>>>> +			       "array bounds of %qT",
>>>> +			       low_sub, up_sub, artype);
>>>> +	}
>>>>   }
>>>> 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);
>>>> +    {
>>>> +      *out_of_bound = true;
>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>>> +			   "array subscript %E is above array bounds of %qT",
>>>> +			   up_sub, artype);
>>>> +    }
>>>> 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);
>>>> +    {
>>>> +      *out_of_bound = true;
>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>>> +			   "array subscript %E is below array bounds of %qT",
>>>> +			   low_sub, artype);
>>>> +    }
>>>> return warned;
>>>> }
>>>> 
>>>> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>> 
>>>> 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);
>>>> +    {
>>>> +      /* 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);
>>>> +    }
>>>> 
>>>> get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
>>>> 
>>>> bool warned = false;
>>>> +  bool out_of_bound = false;
>>>> 
>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>> tree low_sub_org = TREE_OPERAND (ref, 1);
>>>> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>> 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);
>>>> +					 ignore_off_by_one, warn_array_bounds,
>>>> +					 &out_of_bound);
>>>> 
>>>> 
>>>> if (!warned && sam == special_array_member::int_0)
>>>> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
>>>> --- a/gcc/opts.cc
>>>> +++ b/gcc/opts.cc
>>>> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
>>>>     opts->x_profile_flag = 0;
>>>>   }
>>>> 
>>>> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>> index d36ba4d86cb..65c9fec43af 100644
>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>> @@ -1,6 +1,6 @@
>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>> /* { dg-do compile} */
>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
>>>> 
>>>> struct trailing_array_1 {
>>>>   int a;
>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>>   struct trailing_array_4 *trailing_flex)
>>>> {
>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>> index f63206e1948..2b5a895c598 100644
>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>> @@ -1,6 +1,6 @@
>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>> /* { dg-do compile } */
>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
>>>> 
>>>> struct trailing_array_1 {
>>>>   int a;
>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>>   struct trailing_array_4 *trailing_flex)
>>>> {
>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>> 
>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>> index e3273714e8b..25b903f2615 100644
>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>> @@ -1,6 +1,6 @@
>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>> /* { dg-do compile } */
>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
>>>> 
>>>> struct trailing_array_1 {
>>>>   int a;
>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>>   struct trailing_array_4 *trailing_flex)
>>>> {
>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
>>>> 
>>>> }
>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>> index cabaea77dc2..5fc500a19ca 100644
>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>> @@ -1,6 +1,6 @@
>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>> /* { dg-do compile } */
>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>>> 
>>>> struct trailing_array_1 {
>>>>   int a;
>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>>   struct trailing_array_4 *trailing_flex)
>>>> {
>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>> index 8b7db6e4f39..30bb4ca8832 100644
>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>> @@ -1,6 +1,6 @@
>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>> /* { dg-do compile } */
>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>>> 
>>>> struct trailing_array_1 {
>>>>   int a;
>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>>   struct trailing_array_4 *trailing_flex)
>>>> {
>>>>   normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>> 
>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>> index 035bf481396..e847a44516e 100644
>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>> @@ -1,6 +1,6 @@
>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>> /* { dg-do compile } */
>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>>> 
>>>> struct trailing_array_1 {
>>>>   int a;
>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>>   struct trailing_array_4 *trailing_flex)
>>>> {
>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>   trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>> 
>>>> }
>>>> 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..2e241f96208
>>>> --- /dev/null
>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>>>> @@ -0,0 +1,39 @@
>>>> +/* Test -Wstrict-flex-arrays.  */
>>>> +/* { dg-do compile } */
>>>> +/* { 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" } */
>>>> +
>>>> +}
>>>> 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..97eb65ba0a9
>>>> --- /dev/null
>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>>>> @@ -0,0 +1,39 @@
>>>> +/* Test -Wstrict-flex-arrays.  */
>>>> +/* { dg-do compile } */
>>>> +/* { 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" } */
>>>> +
>>>> +}
>>>> 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..110fdc72778
>>>> --- /dev/null
>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>>>> @@ -0,0 +1,39 @@
>>>> +/* Test -Wstrict-flex-arrays.  */
>>>> +/* { dg-do compile } */
>>>> +/* { 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" } */
>>>> +
>>>> +}
>>>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
>>>> index 3846dc1d849..e6c6c5a301d 100644
>>>> --- a/gcc/tree-vrp.cc
>>>> +++ b/gcc/tree-vrp.cc
>>>> @@ -1087,7 +1087,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;
>>>> -- 
>>>> 2.31.1
>>>> 
>>> 
>>> 
>> 
>> -- 
>> 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)
  
Qing Zhao Dec. 14, 2022, 4:40 p.m. UTC | #5
Hi, Richard,

I guess that we now agreed on the following:

“ the information that we ran into a trailing array but didn't consider 
it a flex array because of -fstrict-flex-arrays is always a useful information”

The only thing we didn’t decide is:

A. Amend such new information to -Warray-bounds when -fstrict-flex-arrays=N (N>0) specified.

OR

B. Issue such new information with a new warning option -Wstrict-flex-arrays when -fstrict-flex-arrays=N (N>0) specified.

My current patch implemented B. 

If you think A is better, I will change the patch as A. 

Let me know your opinion.

thanks.

Qing


> On Dec 14, 2022, at 4:03 AM, Richard Biener <rguenther@suse.de> wrote:
> 
> On Tue, 13 Dec 2022, Qing Zhao wrote:
> 
>> Richard, 
>> 
>> Do you have any decision on this one? 
>> Do we need this warning option For GCC? 
> 
> Looking at the testcases it seems that the diagnostic amends
> -Warray-bounds diagnostics for trailing but not flexible arrays?
> Wouldn't it be better to generally diagnose this, so have
> -Warray-bounds, with -fstrict-flex-arrays, for
> 
> struct X { int a[1]; };
> int foo (struct X *p)
> {
>  return p->a[1];
> }
> 
> emit
> 
> warning: array subscript 1 is above array bounds ...
> note: the trailing array is only a flexible array member with 
> -fno-strict-flex-arrays
> 
> ?  Having -Wstrict-flex-arrays=N and N not agree with the
> -fstrict-flex-arrays level sounds hardly useful to me but the
> information that we ran into a trailing array but didn't consider
> it a flex array because of -fstrict-flex-arrays is always a
> useful information?
> 
> But maybe I misunderstood this new diagnostic?
> 
> Thanks,
> Richard.
> 
> 
>> thanks.
>> 
>> Qing
>> 
>>> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
>>> 
>>> gcc/ChangeLog:
>>> 
>>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
>>> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
>>> 	arguments.
>>> 	(array_bounds_checker::check_array_ref): Issue warnings for
>>> 	-Wstrict-flex-arrays.
>>> 	* opts.cc (finish_options): Issue warning for unsupported combination
>>> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
>>> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
>>> 	warn_strict_flex_array is true.
>>> 
>>> gcc/c-family/ChangeLog:
>>> 
>>> 	* c.opt (Wstrict-flex-arrays): New option.
>>> 
>>> gcc/testsuite/ChangeLog:
>>> 
>>> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
>>> 	-Wstrict-flex-arrays.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
>>> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
>>> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
>>> ---
>>> gcc/c-family/c.opt                            |   5 +
>>> gcc/doc/invoke.texi                           |  27 ++++-
>>> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
>>> gcc/opts.cc                                   |   8 ++
>>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
>>> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
>>> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
>>> gcc/tree-vrp.cc                               |   2 +-
>>> 15 files changed, 273 insertions(+), 34 deletions(-)
>>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
>>> 
>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>> index 0d0ad0a6374..33edeefd285 100644
>>> --- a/gcc/c-family/c.opt
>>> +++ b/gcc/c-family/c.opt
>>> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
>>> index 726392409b6..4402b0427ef 100644
>>> --- a/gcc/doc/invoke.texi
>>> +++ b/gcc/doc/invoke.texi
>>> @@ -398,7 +398,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
>>> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
>>> --- a/gcc/gimple-array-bounds.cc
>>> +++ b/gcc/gimple-array-bounds.cc
>>> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
>>> 
>>> /* 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.
>>> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
>>> +   When out of bounds, set OUT_OF_BOUND to true.
>>> +   Issue warnings if FOR_ARRAY_BOUND is true.
>>> +   return TRUE if warnings are issued.  */
>>> +
>>> 
>>> 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 ignore_off_by_one, bool for_array_bound,
>>> +			      bool *out_of_bound)
>>> {
>>>  tree low_bound = array_ref_low_bound (ref);
>>>  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>> 
>>>  bool warned = false;
>>> +  *out_of_bound = 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_org, artype);
>>> +    {
>>> +      *out_of_bound = true;
>>> +      if (for_array_bound)
>>> +	warned = warning_at (location, OPT_Warray_bounds_,
>>> +			     "array subscript %E is outside array"
>>> +			     " bounds of %qT", low_sub_org, artype);
>>> +    }
>>> 
>>>  if (warned)
>>>    ; /* Do nothing.  */
>>> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
>>> +	{
>>> +	  *out_of_bound = true;
>>> +	  warned = warning_at (location, OPT_Warray_bounds_,
>>> +			       "array subscript [%E, %E] is outside "
>>> +			       "array bounds of %qT",
>>> +			       low_sub, up_sub, artype);
>>> +	}
>>>    }
>>>  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);
>>> +    {
>>> +      *out_of_bound = true;
>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>> +			   "array subscript %E is above array bounds of %qT",
>>> +			   up_sub, artype);
>>> +    }
>>>  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);
>>> +    {
>>> +      *out_of_bound = true;
>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>> +			   "array subscript %E is below array bounds of %qT",
>>> +			   low_sub, artype);
>>> +    }
>>>  return warned;
>>> }
>>> 
>>> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>> 
>>>  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);
>>> +    {
>>> +      /* 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);
>>> +    }
>>> 
>>>  get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
>>> 
>>>  bool warned = false;
>>> +  bool out_of_bound = false;
>>> 
>>>  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>  tree low_sub_org = TREE_OPERAND (ref, 1);
>>> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>  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);
>>> +					 ignore_off_by_one, warn_array_bounds,
>>> +					 &out_of_bound);
>>> 
>>> 
>>>  if (!warned && sam == special_array_member::int_0)
>>> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
>>> --- a/gcc/opts.cc
>>> +++ b/gcc/opts.cc
>>> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
>>>      opts->x_profile_flag = 0;
>>>    }
>>> 
>>> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>> index d36ba4d86cb..65c9fec43af 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile} */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>> index f63206e1948..2b5a895c598 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> 
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>> index e3273714e8b..25b903f2615 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>    trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
>>> 
>>> }
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>> index cabaea77dc2..5fc500a19ca 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>> index 8b7db6e4f39..30bb4ca8832 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> 
>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>> index 035bf481396..e847a44516e 100644
>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>> @@ -1,6 +1,6 @@
>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>> /* { dg-do compile } */
>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>> 
>>> struct trailing_array_1 {
>>>    int a;
>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>    struct trailing_array_4 *trailing_flex)
>>> {
>>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>    trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>> 
>>> }
>>> 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..2e241f96208
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>>> @@ -0,0 +1,39 @@
>>> +/* Test -Wstrict-flex-arrays.  */
>>> +/* { dg-do compile } */
>>> +/* { 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" } */
>>> +
>>> +}
>>> 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..97eb65ba0a9
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>>> @@ -0,0 +1,39 @@
>>> +/* Test -Wstrict-flex-arrays.  */
>>> +/* { dg-do compile } */
>>> +/* { 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" } */
>>> +
>>> +}
>>> 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..110fdc72778
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>>> @@ -0,0 +1,39 @@
>>> +/* Test -Wstrict-flex-arrays.  */
>>> +/* { dg-do compile } */
>>> +/* { 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" } */
>>> +
>>> +}
>>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
>>> index 3846dc1d849..e6c6c5a301d 100644
>>> --- a/gcc/tree-vrp.cc
>>> +++ b/gcc/tree-vrp.cc
>>> @@ -1087,7 +1087,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;
>>> -- 
>>> 2.31.1
>>> 
>> 
>> 
> 
> -- 
> 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 Dec. 15, 2022, 7:47 a.m. UTC | #6
On Wed, 14 Dec 2022, Qing Zhao wrote:

> Hi, Richard,
> 
> I guess that we now agreed on the following:
> 
> “ the information that we ran into a trailing array but didn't consider 
> it a flex array because of -fstrict-flex-arrays is always a useful information”
> 
> The only thing we didn’t decide is:
> 
> A. Amend such new information to -Warray-bounds when -fstrict-flex-arrays=N (N>0) specified.
> 
> OR
> 
> B. Issue such new information with a new warning option -Wstrict-flex-arrays when -fstrict-flex-arrays=N (N>0) specified.
> 
> My current patch implemented B. 

Plus it implements it to specify a different flex-array variant for
the extra diagnostic.

> If you think A is better, I will change the patch as A. 

I would tend to A since, as I said, it's useful information that
shouldn't be hidden and not adding an option removes odd combination
possibilities such as -Wno-array-bounds -Wstrict-flex-arrays.
In particular I find, say, -fstrict-flex-arrays=2 -Wstrict-flex-arrays=1
hardly useful.

But I'm interested in other opinions.

Thanks,
Richard.

> Let me know your opinion.
> 
> thanks.
> 
> Qing
> 
> 
> > On Dec 14, 2022, at 4:03 AM, Richard Biener <rguenther@suse.de> wrote:
> > 
> > On Tue, 13 Dec 2022, Qing Zhao wrote:
> > 
> >> Richard, 
> >> 
> >> Do you have any decision on this one? 
> >> Do we need this warning option For GCC? 
> > 
> > Looking at the testcases it seems that the diagnostic amends
> > -Warray-bounds diagnostics for trailing but not flexible arrays?
> > Wouldn't it be better to generally diagnose this, so have
> > -Warray-bounds, with -fstrict-flex-arrays, for
> > 
> > struct X { int a[1]; };
> > int foo (struct X *p)
> > {
> >  return p->a[1];
> > }
> > 
> > emit
> > 
> > warning: array subscript 1 is above array bounds ...
> > note: the trailing array is only a flexible array member with 
> > -fno-strict-flex-arrays
> > 
> > ?  Having -Wstrict-flex-arrays=N and N not agree with the
> > -fstrict-flex-arrays level sounds hardly useful to me but the
> > information that we ran into a trailing array but didn't consider
> > it a flex array because of -fstrict-flex-arrays is always a
> > useful information?
> > 
> > But maybe I misunderstood this new diagnostic?
> > 
> > Thanks,
> > Richard.
> > 
> > 
> >> thanks.
> >> 
> >> Qing
> >> 
> >>> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
> >>> 
> >>> gcc/ChangeLog:
> >>> 
> >>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
> >>> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
> >>> 	arguments.
> >>> 	(array_bounds_checker::check_array_ref): Issue warnings for
> >>> 	-Wstrict-flex-arrays.
> >>> 	* opts.cc (finish_options): Issue warning for unsupported combination
> >>> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
> >>> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
> >>> 	warn_strict_flex_array is true.
> >>> 
> >>> gcc/c-family/ChangeLog:
> >>> 
> >>> 	* c.opt (Wstrict-flex-arrays): New option.
> >>> 
> >>> gcc/testsuite/ChangeLog:
> >>> 
> >>> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
> >>> 	-Wstrict-flex-arrays.
> >>> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
> >>> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
> >>> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
> >>> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
> >>> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
> >>> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
> >>> ---
> >>> gcc/c-family/c.opt                            |   5 +
> >>> gcc/doc/invoke.texi                           |  27 ++++-
> >>> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
> >>> gcc/opts.cc                                   |   8 ++
> >>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
> >>> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
> >>> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
> >>> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
> >>> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
> >>> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
> >>> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
> >>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
> >>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
> >>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
> >>> gcc/tree-vrp.cc                               |   2 +-
> >>> 15 files changed, 273 insertions(+), 34 deletions(-)
> >>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
> >>> 
> >>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> >>> index 0d0ad0a6374..33edeefd285 100644
> >>> --- a/gcc/c-family/c.opt
> >>> +++ b/gcc/c-family/c.opt
> >>> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
> >>> index 726392409b6..4402b0427ef 100644
> >>> --- a/gcc/doc/invoke.texi
> >>> +++ b/gcc/doc/invoke.texi
> >>> @@ -398,7 +398,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
> >>> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
> >>> --- a/gcc/gimple-array-bounds.cc
> >>> +++ b/gcc/gimple-array-bounds.cc
> >>> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
> >>> 
> >>> /* 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.
> >>> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
> >>> +   When out of bounds, set OUT_OF_BOUND to true.
> >>> +   Issue warnings if FOR_ARRAY_BOUND is true.
> >>> +   return TRUE if warnings are issued.  */
> >>> +
> >>> 
> >>> 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 ignore_off_by_one, bool for_array_bound,
> >>> +			      bool *out_of_bound)
> >>> {
> >>>  tree low_bound = array_ref_low_bound (ref);
> >>>  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
> >>> 
> >>>  bool warned = false;
> >>> +  *out_of_bound = 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_org, artype);
> >>> +    {
> >>> +      *out_of_bound = true;
> >>> +      if (for_array_bound)
> >>> +	warned = warning_at (location, OPT_Warray_bounds_,
> >>> +			     "array subscript %E is outside array"
> >>> +			     " bounds of %qT", low_sub_org, artype);
> >>> +    }
> >>> 
> >>>  if (warned)
> >>>    ; /* Do nothing.  */
> >>> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
> >>> +	{
> >>> +	  *out_of_bound = true;
> >>> +	  warned = warning_at (location, OPT_Warray_bounds_,
> >>> +			       "array subscript [%E, %E] is outside "
> >>> +			       "array bounds of %qT",
> >>> +			       low_sub, up_sub, artype);
> >>> +	}
> >>>    }
> >>>  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);
> >>> +    {
> >>> +      *out_of_bound = true;
> >>> +      warned = warning_at (location, OPT_Warray_bounds_,
> >>> +			   "array subscript %E is above array bounds of %qT",
> >>> +			   up_sub, artype);
> >>> +    }
> >>>  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);
> >>> +    {
> >>> +      *out_of_bound = true;
> >>> +      warned = warning_at (location, OPT_Warray_bounds_,
> >>> +			   "array subscript %E is below array bounds of %qT",
> >>> +			   low_sub, artype);
> >>> +    }
> >>>  return warned;
> >>> }
> >>> 
> >>> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
> >>> 
> >>>  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);
> >>> +    {
> >>> +      /* 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);
> >>> +    }
> >>> 
> >>>  get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
> >>> 
> >>>  bool warned = false;
> >>> +  bool out_of_bound = false;
> >>> 
> >>>  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
> >>>  tree low_sub_org = TREE_OPERAND (ref, 1);
> >>> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
> >>>  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);
> >>> +					 ignore_off_by_one, warn_array_bounds,
> >>> +					 &out_of_bound);
> >>> 
> >>> 
> >>>  if (!warned && sam == special_array_member::int_0)
> >>> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
> >>> --- a/gcc/opts.cc
> >>> +++ b/gcc/opts.cc
> >>> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
> >>>      opts->x_profile_flag = 0;
> >>>    }
> >>> 
> >>> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> >>> index d36ba4d86cb..65c9fec43af 100644
> >>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> >>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> >>> @@ -1,6 +1,6 @@
> >>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> >>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> >>> /* { dg-do compile} */
> >>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
> >>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
> >>> 
> >>> struct trailing_array_1 {
> >>>    int a;
> >>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
> >>>    struct trailing_array_4 *trailing_flex)
> >>> {
> >>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> >>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
> >>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> >>> index f63206e1948..2b5a895c598 100644
> >>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> >>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> >>> @@ -1,6 +1,6 @@
> >>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> >>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> >>> /* { dg-do compile } */
> >>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
> >>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
> >>> 
> >>> struct trailing_array_1 {
> >>>    int a;
> >>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
> >>>    struct trailing_array_4 *trailing_flex)
> >>> {
> >>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> >>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
> >>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>> 
> >>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> >>> index e3273714e8b..25b903f2615 100644
> >>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> >>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> >>> @@ -1,6 +1,6 @@
> >>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> >>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> >>> /* { dg-do compile } */
> >>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
> >>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
> >>> 
> >>> struct trailing_array_1 {
> >>>    int a;
> >>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
> >>>    struct trailing_array_4 *trailing_flex)
> >>> {
> >>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
> >>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
> >>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
> >>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
> >>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
> >>> 
> >>> }
> >>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> >>> index cabaea77dc2..5fc500a19ca 100644
> >>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> >>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> >>> @@ -1,6 +1,6 @@
> >>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> >>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> >>> /* { dg-do compile } */
> >>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
> >>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
> >>> 
> >>> struct trailing_array_1 {
> >>>    int a;
> >>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
> >>>    struct trailing_array_4 *trailing_flex)
> >>> {
> >>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> >>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
> >>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> >>> index 8b7db6e4f39..30bb4ca8832 100644
> >>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> >>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> >>> @@ -1,6 +1,6 @@
> >>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> >>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> >>> /* { dg-do compile } */
> >>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
> >>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
> >>> 
> >>> struct trailing_array_1 {
> >>>    int a;
> >>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
> >>>    struct trailing_array_4 *trailing_flex)
> >>> {
> >>>    normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
> >>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
> >>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>> 
> >>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> >>> index 035bf481396..e847a44516e 100644
> >>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> >>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> >>> @@ -1,6 +1,6 @@
> >>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> >>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> >>> /* { dg-do compile } */
> >>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
> >>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
> >>> 
> >>> struct trailing_array_1 {
> >>>    int a;
> >>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
> >>>    struct trailing_array_4 *trailing_flex)
> >>> {
> >>>    normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
> >>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
> >>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >>>    trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
> >>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
> >>>    trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>> 
> >>> }
> >>> 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..2e241f96208
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
> >>> @@ -0,0 +1,39 @@
> >>> +/* Test -Wstrict-flex-arrays.  */
> >>> +/* { dg-do compile } */
> >>> +/* { 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" } */
> >>> +
> >>> +}
> >>> 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..97eb65ba0a9
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
> >>> @@ -0,0 +1,39 @@
> >>> +/* Test -Wstrict-flex-arrays.  */
> >>> +/* { dg-do compile } */
> >>> +/* { 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" } */
> >>> +
> >>> +}
> >>> 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..110fdc72778
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
> >>> @@ -0,0 +1,39 @@
> >>> +/* Test -Wstrict-flex-arrays.  */
> >>> +/* { dg-do compile } */
> >>> +/* { 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" } */
> >>> +
> >>> +}
> >>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> >>> index 3846dc1d849..e6c6c5a301d 100644
> >>> --- a/gcc/tree-vrp.cc
> >>> +++ b/gcc/tree-vrp.cc
> >>> @@ -1087,7 +1087,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;
> >>> -- 
> >>> 2.31.1
> >>> 
> >> 
> >> 
> > 
> > -- 
> > 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)
> 
>
  
Qing Zhao Dec. 15, 2022, 3:27 p.m. UTC | #7
> On Dec 15, 2022, at 2:47 AM, Richard Biener <rguenther@suse.de> wrote:
> 
> On Wed, 14 Dec 2022, Qing Zhao wrote:
> 
>> Hi, Richard,
>> 
>> I guess that we now agreed on the following:
>> 
>> “ the information that we ran into a trailing array but didn't consider 
>> it a flex array because of -fstrict-flex-arrays is always a useful information”
>> 
>> The only thing we didn’t decide is:
>> 
>> A. Amend such new information to -Warray-bounds when -fstrict-flex-arrays=N (N>0) specified.
>> 
>> OR
>> 
>> B. Issue such new information with a new warning option -Wstrict-flex-arrays when -fstrict-flex-arrays=N (N>0) specified.
>> 
>> My current patch implemented B. 
> 
> Plus it implements it to specify a different flex-array variant for
> the extra diagnostic.
Could you clarify a little bit on this? (Don’t quite understand…)
> 
>> If you think A is better, I will change the patch as A. 
> 
> I would tend to A since, as I said, it's useful information that
> shouldn't be hidden and not adding an option removes odd combination
> possibilities such as -Wno-array-bounds -Wstrict-flex-arrays.

With current implementation, the above combination will ONLY report the misuse of trailing array as flex-array.  No out-of-bounds warnings issued.

> In particular I find, say, -fstrict-flex-arrays=2 -Wstrict-flex-arrays=1
> hardly useful.

The above combination will NOT happen, because there is NO level argument for -Wstrict-flex-arrays.

The only combination will be:    -fstrict-flex-arrays=N -Wstrict-flex-arrays

When N > 0, -Wstrict-flex-arrays will report any misuse of trailing arrays as flexible array per the value of N.
> 
> But I'm interested in other opinions.

Adding a separate -Wstrict-flex-arrays will provide users a choice to ONLY look at the mis-use of trailing arrays as flex-arrays.  Without this new option, such information will be buried into tons of out-of-bounds messges. 

I think this is the major benefit to have one separate new warning -Wstrict-flex-arrays. 

Do we need to provide the users this choice?

Thanks.

Qing
> 
> Thanks,
> Richard.
> 
>> Let me know your opinion.
>> 
>> thanks.
>> 
>> Qing
>> 
>> 
>>> On Dec 14, 2022, at 4:03 AM, Richard Biener <rguenther@suse.de> wrote:
>>> 
>>> On Tue, 13 Dec 2022, Qing Zhao wrote:
>>> 
>>>> Richard, 
>>>> 
>>>> Do you have any decision on this one? 
>>>> Do we need this warning option For GCC? 
>>> 
>>> Looking at the testcases it seems that the diagnostic amends
>>> -Warray-bounds diagnostics for trailing but not flexible arrays?
>>> Wouldn't it be better to generally diagnose this, so have
>>> -Warray-bounds, with -fstrict-flex-arrays, for
>>> 
>>> struct X { int a[1]; };
>>> int foo (struct X *p)
>>> {
>>> return p->a[1];
>>> }
>>> 
>>> emit
>>> 
>>> warning: array subscript 1 is above array bounds ...
>>> note: the trailing array is only a flexible array member with 
>>> -fno-strict-flex-arrays
>>> 
>>> ?  Having -Wstrict-flex-arrays=N and N not agree with the
>>> -fstrict-flex-arrays level sounds hardly useful to me but the
>>> information that we ran into a trailing array but didn't consider
>>> it a flex array because of -fstrict-flex-arrays is always a
>>> useful information?
>>> 
>>> But maybe I misunderstood this new diagnostic?
>>> 
>>> Thanks,
>>> Richard.
>>> 
>>> 
>>>> thanks.
>>>> 
>>>> Qing
>>>> 
>>>>> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
>>>>> 
>>>>> gcc/ChangeLog:
>>>>> 
>>>>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
>>>>> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
>>>>> 	arguments.
>>>>> 	(array_bounds_checker::check_array_ref): Issue warnings for
>>>>> 	-Wstrict-flex-arrays.
>>>>> 	* opts.cc (finish_options): Issue warning for unsupported combination
>>>>> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
>>>>> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
>>>>> 	warn_strict_flex_array is true.
>>>>> 
>>>>> gcc/c-family/ChangeLog:
>>>>> 
>>>>> 	* c.opt (Wstrict-flex-arrays): New option.
>>>>> 
>>>>> gcc/testsuite/ChangeLog:
>>>>> 
>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
>>>>> 	-Wstrict-flex-arrays.
>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
>>>>> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
>>>>> ---
>>>>> gcc/c-family/c.opt                            |   5 +
>>>>> gcc/doc/invoke.texi                           |  27 ++++-
>>>>> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
>>>>> gcc/opts.cc                                   |   8 ++
>>>>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
>>>>> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
>>>>> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
>>>>> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
>>>>> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
>>>>> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
>>>>> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
>>>>> gcc/tree-vrp.cc                               |   2 +-
>>>>> 15 files changed, 273 insertions(+), 34 deletions(-)
>>>>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
>>>>> 
>>>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>>>> index 0d0ad0a6374..33edeefd285 100644
>>>>> --- a/gcc/c-family/c.opt
>>>>> +++ b/gcc/c-family/c.opt
>>>>> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
>>>>> index 726392409b6..4402b0427ef 100644
>>>>> --- a/gcc/doc/invoke.texi
>>>>> +++ b/gcc/doc/invoke.texi
>>>>> @@ -398,7 +398,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
>>>>> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
>>>>> --- a/gcc/gimple-array-bounds.cc
>>>>> +++ b/gcc/gimple-array-bounds.cc
>>>>> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
>>>>> 
>>>>> /* 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.
>>>>> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
>>>>> +   When out of bounds, set OUT_OF_BOUND to true.
>>>>> +   Issue warnings if FOR_ARRAY_BOUND is true.
>>>>> +   return TRUE if warnings are issued.  */
>>>>> +
>>>>> 
>>>>> 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 ignore_off_by_one, bool for_array_bound,
>>>>> +			      bool *out_of_bound)
>>>>> {
>>>>> tree low_bound = array_ref_low_bound (ref);
>>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>>> 
>>>>> bool warned = false;
>>>>> +  *out_of_bound = 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_org, artype);
>>>>> +    {
>>>>> +      *out_of_bound = true;
>>>>> +      if (for_array_bound)
>>>>> +	warned = warning_at (location, OPT_Warray_bounds_,
>>>>> +			     "array subscript %E is outside array"
>>>>> +			     " bounds of %qT", low_sub_org, artype);
>>>>> +    }
>>>>> 
>>>>> if (warned)
>>>>>   ; /* Do nothing.  */
>>>>> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
>>>>> +	{
>>>>> +	  *out_of_bound = true;
>>>>> +	  warned = warning_at (location, OPT_Warray_bounds_,
>>>>> +			       "array subscript [%E, %E] is outside "
>>>>> +			       "array bounds of %qT",
>>>>> +			       low_sub, up_sub, artype);
>>>>> +	}
>>>>>   }
>>>>> 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);
>>>>> +    {
>>>>> +      *out_of_bound = true;
>>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>>>> +			   "array subscript %E is above array bounds of %qT",
>>>>> +			   up_sub, artype);
>>>>> +    }
>>>>> 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);
>>>>> +    {
>>>>> +      *out_of_bound = true;
>>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>>>> +			   "array subscript %E is below array bounds of %qT",
>>>>> +			   low_sub, artype);
>>>>> +    }
>>>>> return warned;
>>>>> }
>>>>> 
>>>>> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>>> 
>>>>> 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);
>>>>> +    {
>>>>> +      /* 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);
>>>>> +    }
>>>>> 
>>>>> get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
>>>>> 
>>>>> bool warned = false;
>>>>> +  bool out_of_bound = false;
>>>>> 
>>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>>> tree low_sub_org = TREE_OPERAND (ref, 1);
>>>>> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>>> 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);
>>>>> +					 ignore_off_by_one, warn_array_bounds,
>>>>> +					 &out_of_bound);
>>>>> 
>>>>> 
>>>>> if (!warned && sam == special_array_member::int_0)
>>>>> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
>>>>> --- a/gcc/opts.cc
>>>>> +++ b/gcc/opts.cc
>>>>> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
>>>>>     opts->x_profile_flag = 0;
>>>>>   }
>>>>> 
>>>>> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>> index d36ba4d86cb..65c9fec43af 100644
>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>> @@ -1,6 +1,6 @@
>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>> /* { dg-do compile} */
>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
>>>>> 
>>>>> struct trailing_array_1 {
>>>>>   int a;
>>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>>>   struct trailing_array_4 *trailing_flex)
>>>>> {
>>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>> index f63206e1948..2b5a895c598 100644
>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>> @@ -1,6 +1,6 @@
>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>> /* { dg-do compile } */
>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
>>>>> 
>>>>> struct trailing_array_1 {
>>>>>   int a;
>>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>>>   struct trailing_array_4 *trailing_flex)
>>>>> {
>>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>> 
>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>> index e3273714e8b..25b903f2615 100644
>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>> @@ -1,6 +1,6 @@
>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>> /* { dg-do compile } */
>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
>>>>> 
>>>>> struct trailing_array_1 {
>>>>>   int a;
>>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>>>   struct trailing_array_4 *trailing_flex)
>>>>> {
>>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
>>>>> 
>>>>> }
>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>> index cabaea77dc2..5fc500a19ca 100644
>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>> @@ -1,6 +1,6 @@
>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>> /* { dg-do compile } */
>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>>>> 
>>>>> struct trailing_array_1 {
>>>>>   int a;
>>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>>>   struct trailing_array_4 *trailing_flex)
>>>>> {
>>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>> index 8b7db6e4f39..30bb4ca8832 100644
>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>> @@ -1,6 +1,6 @@
>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>> /* { dg-do compile } */
>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>>>> 
>>>>> struct trailing_array_1 {
>>>>>   int a;
>>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>>>   struct trailing_array_4 *trailing_flex)
>>>>> {
>>>>>   normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>> 
>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>> index 035bf481396..e847a44516e 100644
>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>> @@ -1,6 +1,6 @@
>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>> /* { dg-do compile } */
>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>>>> 
>>>>> struct trailing_array_1 {
>>>>>   int a;
>>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>>>   struct trailing_array_4 *trailing_flex)
>>>>> {
>>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>   trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>> 
>>>>> }
>>>>> 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..2e241f96208
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>>>>> @@ -0,0 +1,39 @@
>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>> +/* { dg-do compile } */
>>>>> +/* { 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" } */
>>>>> +
>>>>> +}
>>>>> 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..97eb65ba0a9
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>>>>> @@ -0,0 +1,39 @@
>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>> +/* { dg-do compile } */
>>>>> +/* { 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" } */
>>>>> +
>>>>> +}
>>>>> 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..110fdc72778
>>>>> --- /dev/null
>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>>>>> @@ -0,0 +1,39 @@
>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>> +/* { dg-do compile } */
>>>>> +/* { 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" } */
>>>>> +
>>>>> +}
>>>>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
>>>>> index 3846dc1d849..e6c6c5a301d 100644
>>>>> --- a/gcc/tree-vrp.cc
>>>>> +++ b/gcc/tree-vrp.cc
>>>>> @@ -1087,7 +1087,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;
>>>>> -- 
>>>>> 2.31.1
>>>>> 
>>>> 
>>>> 
>>> 
>>> -- 
>>> 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)
  
Richard Biener Dec. 16, 2022, 9:17 a.m. UTC | #8
On Thu, 15 Dec 2022, Qing Zhao wrote:

> 
> 
> > On Dec 15, 2022, at 2:47 AM, Richard Biener <rguenther@suse.de> wrote:
> > 
> > On Wed, 14 Dec 2022, Qing Zhao wrote:
> > 
> >> Hi, Richard,
> >> 
> >> I guess that we now agreed on the following:
> >> 
> >> “ the information that we ran into a trailing array but didn't consider 
> >> it a flex array because of -fstrict-flex-arrays is always a useful information”
> >> 
> >> The only thing we didn’t decide is:
> >> 
> >> A. Amend such new information to -Warray-bounds when -fstrict-flex-arrays=N (N>0) specified.
> >> 
> >> OR
> >> 
> >> B. Issue such new information with a new warning option -Wstrict-flex-arrays when -fstrict-flex-arrays=N (N>0) specified.
> >> 
> >> My current patch implemented B. 
> > 
> > Plus it implements it to specify a different flex-array variant for
> > the extra diagnostic.
> Could you clarify a little bit on this? (Don’t quite understand…)
> > 
> >> If you think A is better, I will change the patch as A. 
> > 
> > I would tend to A since, as I said, it's useful information that
> > shouldn't be hidden and not adding an option removes odd combination
> > possibilities such as -Wno-array-bounds -Wstrict-flex-arrays.
> 
> With current implementation, the above combination will ONLY report the 
> misuse of trailing array as flex-array.  No out-of-bounds warnings 
> issued.
> 
> > In particular I find, say, -fstrict-flex-arrays=2 -Wstrict-flex-arrays=1
> > hardly useful.
> 
> The above combination will NOT happen, because there is NO level argument for -Wstrict-flex-arrays.
> 
> The only combination will be:    -fstrict-flex-arrays=N -Wstrict-flex-arrays
> 
> When N > 0, -Wstrict-flex-arrays will report any misuse of trailing arrays as flexible array per the value of N.
> > 
> > But I'm interested in other opinions.
> 
> Adding a separate -Wstrict-flex-arrays will provide users a choice to ONLY look at the mis-use of trailing arrays as flex-arrays.  Without this new option, such information will be buried into tons of out-of-bounds messges. 
> 
> I think this is the major benefit to have one separate new warning -Wstrict-flex-arrays. 
> 
> Do we need to provide the users this choice?

Ah, OK - I can see the value of auditing code this way before
enabling -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");

"is not present".

The patch is OK with that change.

Thanks and sorry for the slow process ...

Richard.

> Thanks.
> 
> Qing
> > 
> > Thanks,
> > Richard.
> > 
> >> Let me know your opinion.
> >> 
> >> thanks.
> >> 
> >> Qing
> >> 
> >> 
> >>> On Dec 14, 2022, at 4:03 AM, Richard Biener <rguenther@suse.de> wrote:
> >>> 
> >>> On Tue, 13 Dec 2022, Qing Zhao wrote:
> >>> 
> >>>> Richard, 
> >>>> 
> >>>> Do you have any decision on this one? 
> >>>> Do we need this warning option For GCC? 
> >>> 
> >>> Looking at the testcases it seems that the diagnostic amends
> >>> -Warray-bounds diagnostics for trailing but not flexible arrays?
> >>> Wouldn't it be better to generally diagnose this, so have
> >>> -Warray-bounds, with -fstrict-flex-arrays, for
> >>> 
> >>> struct X { int a[1]; };
> >>> int foo (struct X *p)
> >>> {
> >>> return p->a[1];
> >>> }
> >>> 
> >>> emit
> >>> 
> >>> warning: array subscript 1 is above array bounds ...
> >>> note: the trailing array is only a flexible array member with 
> >>> -fno-strict-flex-arrays
> >>> 
> >>> ?  Having -Wstrict-flex-arrays=N and N not agree with the
> >>> -fstrict-flex-arrays level sounds hardly useful to me but the
> >>> information that we ran into a trailing array but didn't consider
> >>> it a flex array because of -fstrict-flex-arrays is always a
> >>> useful information?
> >>> 
> >>> But maybe I misunderstood this new diagnostic?
> >>> 
> >>> Thanks,
> >>> Richard.
> >>> 
> >>> 
> >>>> thanks.
> >>>> 
> >>>> Qing
> >>>> 
> >>>>> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
> >>>>> 
> >>>>> gcc/ChangeLog:
> >>>>> 
> >>>>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
> >>>>> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
> >>>>> 	arguments.
> >>>>> 	(array_bounds_checker::check_array_ref): Issue warnings for
> >>>>> 	-Wstrict-flex-arrays.
> >>>>> 	* opts.cc (finish_options): Issue warning for unsupported combination
> >>>>> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
> >>>>> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
> >>>>> 	warn_strict_flex_array is true.
> >>>>> 
> >>>>> gcc/c-family/ChangeLog:
> >>>>> 
> >>>>> 	* c.opt (Wstrict-flex-arrays): New option.
> >>>>> 
> >>>>> gcc/testsuite/ChangeLog:
> >>>>> 
> >>>>> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
> >>>>> 	-Wstrict-flex-arrays.
> >>>>> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
> >>>>> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
> >>>>> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
> >>>>> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
> >>>>> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
> >>>>> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
> >>>>> ---
> >>>>> gcc/c-family/c.opt                            |   5 +
> >>>>> gcc/doc/invoke.texi                           |  27 ++++-
> >>>>> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
> >>>>> gcc/opts.cc                                   |   8 ++
> >>>>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
> >>>>> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
> >>>>> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
> >>>>> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
> >>>>> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
> >>>>> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
> >>>>> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
> >>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
> >>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
> >>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
> >>>>> gcc/tree-vrp.cc                               |   2 +-
> >>>>> 15 files changed, 273 insertions(+), 34 deletions(-)
> >>>>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
> >>>>> 
> >>>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> >>>>> index 0d0ad0a6374..33edeefd285 100644
> >>>>> --- a/gcc/c-family/c.opt
> >>>>> +++ b/gcc/c-family/c.opt
> >>>>> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
> >>>>> index 726392409b6..4402b0427ef 100644
> >>>>> --- a/gcc/doc/invoke.texi
> >>>>> +++ b/gcc/doc/invoke.texi
> >>>>> @@ -398,7 +398,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
> >>>>> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
> >>>>> --- a/gcc/gimple-array-bounds.cc
> >>>>> +++ b/gcc/gimple-array-bounds.cc
> >>>>> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
> >>>>> 
> >>>>> /* 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.
> >>>>> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
> >>>>> +   When out of bounds, set OUT_OF_BOUND to true.
> >>>>> +   Issue warnings if FOR_ARRAY_BOUND is true.
> >>>>> +   return TRUE if warnings are issued.  */
> >>>>> +
> >>>>> 
> >>>>> 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 ignore_off_by_one, bool for_array_bound,
> >>>>> +			      bool *out_of_bound)
> >>>>> {
> >>>>> tree low_bound = array_ref_low_bound (ref);
> >>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
> >>>>> 
> >>>>> bool warned = false;
> >>>>> +  *out_of_bound = 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_org, artype);
> >>>>> +    {
> >>>>> +      *out_of_bound = true;
> >>>>> +      if (for_array_bound)
> >>>>> +	warned = warning_at (location, OPT_Warray_bounds_,
> >>>>> +			     "array subscript %E is outside array"
> >>>>> +			     " bounds of %qT", low_sub_org, artype);
> >>>>> +    }
> >>>>> 
> >>>>> if (warned)
> >>>>>   ; /* Do nothing.  */
> >>>>> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
> >>>>> +	{
> >>>>> +	  *out_of_bound = true;
> >>>>> +	  warned = warning_at (location, OPT_Warray_bounds_,
> >>>>> +			       "array subscript [%E, %E] is outside "
> >>>>> +			       "array bounds of %qT",
> >>>>> +			       low_sub, up_sub, artype);
> >>>>> +	}
> >>>>>   }
> >>>>> 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);
> >>>>> +    {
> >>>>> +      *out_of_bound = true;
> >>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
> >>>>> +			   "array subscript %E is above array bounds of %qT",
> >>>>> +			   up_sub, artype);
> >>>>> +    }
> >>>>> 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);
> >>>>> +    {
> >>>>> +      *out_of_bound = true;
> >>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
> >>>>> +			   "array subscript %E is below array bounds of %qT",
> >>>>> +			   low_sub, artype);
> >>>>> +    }
> >>>>> return warned;
> >>>>> }
> >>>>> 
> >>>>> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
> >>>>> 
> >>>>> 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);
> >>>>> +    {
> >>>>> +      /* 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);
> >>>>> +    }
> >>>>> 
> >>>>> get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
> >>>>> 
> >>>>> bool warned = false;
> >>>>> +  bool out_of_bound = false;
> >>>>> 
> >>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
> >>>>> tree low_sub_org = TREE_OPERAND (ref, 1);
> >>>>> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
> >>>>> 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);
> >>>>> +					 ignore_off_by_one, warn_array_bounds,
> >>>>> +					 &out_of_bound);
> >>>>> 
> >>>>> 
> >>>>> if (!warned && sam == special_array_member::int_0)
> >>>>> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
> >>>>> --- a/gcc/opts.cc
> >>>>> +++ b/gcc/opts.cc
> >>>>> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
> >>>>>     opts->x_profile_flag = 0;
> >>>>>   }
> >>>>> 
> >>>>> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> >>>>> index d36ba4d86cb..65c9fec43af 100644
> >>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> >>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
> >>>>> @@ -1,6 +1,6 @@
> >>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> >>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> >>>>> /* { dg-do compile} */
> >>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
> >>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
> >>>>> 
> >>>>> struct trailing_array_1 {
> >>>>>   int a;
> >>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
> >>>>>   struct trailing_array_4 *trailing_flex)
> >>>>> {
> >>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> >>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
> >>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> >>>>> index f63206e1948..2b5a895c598 100644
> >>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> >>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
> >>>>> @@ -1,6 +1,6 @@
> >>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> >>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> >>>>> /* { dg-do compile } */
> >>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
> >>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
> >>>>> 
> >>>>> struct trailing_array_1 {
> >>>>>   int a;
> >>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
> >>>>>   struct trailing_array_4 *trailing_flex)
> >>>>> {
> >>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> >>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
> >>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>>>> 
> >>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> >>>>> index e3273714e8b..25b903f2615 100644
> >>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> >>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
> >>>>> @@ -1,6 +1,6 @@
> >>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
> >>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
> >>>>> /* { dg-do compile } */
> >>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
> >>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
> >>>>> 
> >>>>> struct trailing_array_1 {
> >>>>>   int a;
> >>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
> >>>>>   struct trailing_array_4 *trailing_flex)
> >>>>> {
> >>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
> >>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
> >>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
> >>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
> >>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
> >>>>> 
> >>>>> }
> >>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> >>>>> index cabaea77dc2..5fc500a19ca 100644
> >>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> >>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
> >>>>> @@ -1,6 +1,6 @@
> >>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> >>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> >>>>> /* { dg-do compile } */
> >>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
> >>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
> >>>>> 
> >>>>> struct trailing_array_1 {
> >>>>>   int a;
> >>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
> >>>>>   struct trailing_array_4 *trailing_flex)
> >>>>> {
> >>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
> >>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
> >>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> >>>>> index 8b7db6e4f39..30bb4ca8832 100644
> >>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> >>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
> >>>>> @@ -1,6 +1,6 @@
> >>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> >>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> >>>>> /* { dg-do compile } */
> >>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
> >>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
> >>>>> 
> >>>>> struct trailing_array_1 {
> >>>>>   int a;
> >>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
> >>>>>   struct trailing_array_4 *trailing_flex)
> >>>>> {
> >>>>>   normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
> >>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
> >>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
> >>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>>>> 
> >>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> >>>>> index 035bf481396..e847a44516e 100644
> >>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> >>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
> >>>>> @@ -1,6 +1,6 @@
> >>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
> >>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
> >>>>> /* { dg-do compile } */
> >>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
> >>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
> >>>>> 
> >>>>> struct trailing_array_1 {
> >>>>>   int a;
> >>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
> >>>>>   struct trailing_array_4 *trailing_flex)
> >>>>> {
> >>>>>   normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
> >>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
> >>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
> >>>>>   trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
> >>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
> >>>>>   trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
> >>>>> 
> >>>>> }
> >>>>> 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..2e241f96208
> >>>>> --- /dev/null
> >>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
> >>>>> @@ -0,0 +1,39 @@
> >>>>> +/* Test -Wstrict-flex-arrays.  */
> >>>>> +/* { dg-do compile } */
> >>>>> +/* { 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" } */
> >>>>> +
> >>>>> +}
> >>>>> 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..97eb65ba0a9
> >>>>> --- /dev/null
> >>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
> >>>>> @@ -0,0 +1,39 @@
> >>>>> +/* Test -Wstrict-flex-arrays.  */
> >>>>> +/* { dg-do compile } */
> >>>>> +/* { 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" } */
> >>>>> +
> >>>>> +}
> >>>>> 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..110fdc72778
> >>>>> --- /dev/null
> >>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
> >>>>> @@ -0,0 +1,39 @@
> >>>>> +/* Test -Wstrict-flex-arrays.  */
> >>>>> +/* { dg-do compile } */
> >>>>> +/* { 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" } */
> >>>>> +
> >>>>> +}
> >>>>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> >>>>> index 3846dc1d849..e6c6c5a301d 100644
> >>>>> --- a/gcc/tree-vrp.cc
> >>>>> +++ b/gcc/tree-vrp.cc
> >>>>> @@ -1087,7 +1087,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;
> >>>>> -- 
> >>>>> 2.31.1
> >>>>> 
> >>>> 
> >>>> 
> >>> 
> >>> -- 
> >>> 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)
> 
>
  
Qing Zhao Dec. 16, 2022, 2:49 p.m. UTC | #9
> On Dec 16, 2022, at 4:17 AM, Richard Biener <rguenther@suse.de> wrote:
> 
> On Thu, 15 Dec 2022, Qing Zhao wrote:
> 
>> 
>> 
>>> On Dec 15, 2022, at 2:47 AM, Richard Biener <rguenther@suse.de> wrote:
>>> 
>>> On Wed, 14 Dec 2022, Qing Zhao wrote:
>>> 
>>>> Hi, Richard,
>>>> 
>>>> I guess that we now agreed on the following:
>>>> 
>>>> “ the information that we ran into a trailing array but didn't consider 
>>>> it a flex array because of -fstrict-flex-arrays is always a useful information”
>>>> 
>>>> The only thing we didn’t decide is:
>>>> 
>>>> A. Amend such new information to -Warray-bounds when -fstrict-flex-arrays=N (N>0) specified.
>>>> 
>>>> OR
>>>> 
>>>> B. Issue such new information with a new warning option -Wstrict-flex-arrays when -fstrict-flex-arrays=N (N>0) specified.
>>>> 
>>>> My current patch implemented B. 
>>> 
>>> Plus it implements it to specify a different flex-array variant for
>>> the extra diagnostic.
>> Could you clarify a little bit on this? (Don’t quite understand…)
>>> 
>>>> If you think A is better, I will change the patch as A. 
>>> 
>>> I would tend to A since, as I said, it's useful information that
>>> shouldn't be hidden and not adding an option removes odd combination
>>> possibilities such as -Wno-array-bounds -Wstrict-flex-arrays.
>> 
>> With current implementation, the above combination will ONLY report the 
>> misuse of trailing array as flex-array.  No out-of-bounds warnings 
>> issued.
>> 
>>> In particular I find, say, -fstrict-flex-arrays=2 -Wstrict-flex-arrays=1
>>> hardly useful.
>> 
>> The above combination will NOT happen, because there is NO level argument for -Wstrict-flex-arrays.
>> 
>> The only combination will be:    -fstrict-flex-arrays=N -Wstrict-flex-arrays
>> 
>> When N > 0, -Wstrict-flex-arrays will report any misuse of trailing arrays as flexible array per the value of N.
>>> 
>>> But I'm interested in other opinions.
>> 
>> Adding a separate -Wstrict-flex-arrays will provide users a choice to ONLY look at the mis-use of trailing arrays as flex-arrays.  Without this new option, such information will be buried into tons of out-of-bounds messges. 
>> 
>> I think this is the major benefit to have one separate new warning -Wstrict-flex-arrays. 
>> 
>> Do we need to provide the users this choice?
> 
> Ah, OK - I can see the value of auditing code this way before
> enabling -fstrict-flex-arrays.
Yes, I think the major benefit of this option is to help users to identify all the places where the trailing arrays are misused as flex-arrays at different level of -fstrict-flex-arrays=N, then update their source code accordingly. And finally can enable -fstrict-flex-arrays by default.
> 
>> +  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");
> 
> "is not present”.
Okay.
> 
> The patch is OK with that change.
Thanks! Will commit the patch after the change.
> 
> Thanks and sorry for the slow process ...

Thank you for your patience and questions.
The discussion is very helpful since I was not 100% sure whether this new warning is necessary or not in the beginning, but now after this discussion I feel confident that it’s a necessary option to be added.

Qing

> 
> Richard.
> 
>> Thanks.
>> 
>> Qing
>>> 
>>> Thanks,
>>> Richard.
>>> 
>>>> Let me know your opinion.
>>>> 
>>>> thanks.
>>>> 
>>>> Qing
>>>> 
>>>> 
>>>>> On Dec 14, 2022, at 4:03 AM, Richard Biener <rguenther@suse.de> wrote:
>>>>> 
>>>>> On Tue, 13 Dec 2022, Qing Zhao wrote:
>>>>> 
>>>>>> Richard, 
>>>>>> 
>>>>>> Do you have any decision on this one? 
>>>>>> Do we need this warning option For GCC? 
>>>>> 
>>>>> Looking at the testcases it seems that the diagnostic amends
>>>>> -Warray-bounds diagnostics for trailing but not flexible arrays?
>>>>> Wouldn't it be better to generally diagnose this, so have
>>>>> -Warray-bounds, with -fstrict-flex-arrays, for
>>>>> 
>>>>> struct X { int a[1]; };
>>>>> int foo (struct X *p)
>>>>> {
>>>>> return p->a[1];
>>>>> }
>>>>> 
>>>>> emit
>>>>> 
>>>>> warning: array subscript 1 is above array bounds ...
>>>>> note: the trailing array is only a flexible array member with 
>>>>> -fno-strict-flex-arrays
>>>>> 
>>>>> ?  Having -Wstrict-flex-arrays=N and N not agree with the
>>>>> -fstrict-flex-arrays level sounds hardly useful to me but the
>>>>> information that we ran into a trailing array but didn't consider
>>>>> it a flex array because of -fstrict-flex-arrays is always a
>>>>> useful information?
>>>>> 
>>>>> But maybe I misunderstood this new diagnostic?
>>>>> 
>>>>> Thanks,
>>>>> Richard.
>>>>> 
>>>>> 
>>>>>> thanks.
>>>>>> 
>>>>>> Qing
>>>>>> 
>>>>>>> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
>>>>>>> 
>>>>>>> gcc/ChangeLog:
>>>>>>> 
>>>>>>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
>>>>>>> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
>>>>>>> 	arguments.
>>>>>>> 	(array_bounds_checker::check_array_ref): Issue warnings for
>>>>>>> 	-Wstrict-flex-arrays.
>>>>>>> 	* opts.cc (finish_options): Issue warning for unsupported combination
>>>>>>> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
>>>>>>> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
>>>>>>> 	warn_strict_flex_array is true.
>>>>>>> 
>>>>>>> gcc/c-family/ChangeLog:
>>>>>>> 
>>>>>>> 	* c.opt (Wstrict-flex-arrays): New option.
>>>>>>> 
>>>>>>> gcc/testsuite/ChangeLog:
>>>>>>> 
>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
>>>>>>> 	-Wstrict-flex-arrays.
>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
>>>>>>> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
>>>>>>> ---
>>>>>>> gcc/c-family/c.opt                            |   5 +
>>>>>>> gcc/doc/invoke.texi                           |  27 ++++-
>>>>>>> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
>>>>>>> gcc/opts.cc                                   |   8 ++
>>>>>>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
>>>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
>>>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
>>>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
>>>>>>> gcc/tree-vrp.cc                               |   2 +-
>>>>>>> 15 files changed, 273 insertions(+), 34 deletions(-)
>>>>>>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
>>>>>>> 
>>>>>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>>>>>> index 0d0ad0a6374..33edeefd285 100644
>>>>>>> --- a/gcc/c-family/c.opt
>>>>>>> +++ b/gcc/c-family/c.opt
>>>>>>> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
>>>>>>> index 726392409b6..4402b0427ef 100644
>>>>>>> --- a/gcc/doc/invoke.texi
>>>>>>> +++ b/gcc/doc/invoke.texi
>>>>>>> @@ -398,7 +398,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
>>>>>>> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
>>>>>>> --- a/gcc/gimple-array-bounds.cc
>>>>>>> +++ b/gcc/gimple-array-bounds.cc
>>>>>>> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
>>>>>>> 
>>>>>>> /* 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.
>>>>>>> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
>>>>>>> +   When out of bounds, set OUT_OF_BOUND to true.
>>>>>>> +   Issue warnings if FOR_ARRAY_BOUND is true.
>>>>>>> +   return TRUE if warnings are issued.  */
>>>>>>> +
>>>>>>> 
>>>>>>> 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 ignore_off_by_one, bool for_array_bound,
>>>>>>> +			      bool *out_of_bound)
>>>>>>> {
>>>>>>> tree low_bound = array_ref_low_bound (ref);
>>>>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>>>>> 
>>>>>>> bool warned = false;
>>>>>>> +  *out_of_bound = 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_org, artype);
>>>>>>> +    {
>>>>>>> +      *out_of_bound = true;
>>>>>>> +      if (for_array_bound)
>>>>>>> +	warned = warning_at (location, OPT_Warray_bounds_,
>>>>>>> +			     "array subscript %E is outside array"
>>>>>>> +			     " bounds of %qT", low_sub_org, artype);
>>>>>>> +    }
>>>>>>> 
>>>>>>> if (warned)
>>>>>>>  ; /* Do nothing.  */
>>>>>>> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
>>>>>>> +	{
>>>>>>> +	  *out_of_bound = true;
>>>>>>> +	  warned = warning_at (location, OPT_Warray_bounds_,
>>>>>>> +			       "array subscript [%E, %E] is outside "
>>>>>>> +			       "array bounds of %qT",
>>>>>>> +			       low_sub, up_sub, artype);
>>>>>>> +	}
>>>>>>>  }
>>>>>>> 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);
>>>>>>> +    {
>>>>>>> +      *out_of_bound = true;
>>>>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>>>>>> +			   "array subscript %E is above array bounds of %qT",
>>>>>>> +			   up_sub, artype);
>>>>>>> +    }
>>>>>>> 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);
>>>>>>> +    {
>>>>>>> +      *out_of_bound = true;
>>>>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>>>>>> +			   "array subscript %E is below array bounds of %qT",
>>>>>>> +			   low_sub, artype);
>>>>>>> +    }
>>>>>>> return warned;
>>>>>>> }
>>>>>>> 
>>>>>>> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>>>>> 
>>>>>>> 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);
>>>>>>> +    {
>>>>>>> +      /* 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);
>>>>>>> +    }
>>>>>>> 
>>>>>>> get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
>>>>>>> 
>>>>>>> bool warned = false;
>>>>>>> +  bool out_of_bound = false;
>>>>>>> 
>>>>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>>>>> tree low_sub_org = TREE_OPERAND (ref, 1);
>>>>>>> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>>>>> 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);
>>>>>>> +					 ignore_off_by_one, warn_array_bounds,
>>>>>>> +					 &out_of_bound);
>>>>>>> 
>>>>>>> 
>>>>>>> if (!warned && sam == special_array_member::int_0)
>>>>>>> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
>>>>>>> --- a/gcc/opts.cc
>>>>>>> +++ b/gcc/opts.cc
>>>>>>> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
>>>>>>>    opts->x_profile_flag = 0;
>>>>>>>  }
>>>>>>> 
>>>>>>> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>>>> index d36ba4d86cb..65c9fec43af 100644
>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>>>> @@ -1,6 +1,6 @@
>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>>>> /* { dg-do compile} */
>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
>>>>>>> 
>>>>>>> struct trailing_array_1 {
>>>>>>>  int a;
>>>>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>  struct trailing_array_4 *trailing_flex)
>>>>>>> {
>>>>>>>  normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>>>>>  trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>>>  trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>>>> index f63206e1948..2b5a895c598 100644
>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>>>> @@ -1,6 +1,6 @@
>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>>>> /* { dg-do compile } */
>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
>>>>>>> 
>>>>>>> struct trailing_array_1 {
>>>>>>>  int a;
>>>>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>  struct trailing_array_4 *trailing_flex)
>>>>>>> {
>>>>>>>  normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>>>  trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>> 
>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>>>> index e3273714e8b..25b903f2615 100644
>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>>>> @@ -1,6 +1,6 @@
>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>>>> /* { dg-do compile } */
>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
>>>>>>> 
>>>>>>> struct trailing_array_1 {
>>>>>>>  int a;
>>>>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>  struct trailing_array_4 *trailing_flex)
>>>>>>> {
>>>>>>>  normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
>>>>>>> 
>>>>>>> }
>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>>>> index cabaea77dc2..5fc500a19ca 100644
>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>>>> @@ -1,6 +1,6 @@
>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>>>> /* { dg-do compile } */
>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>>>>>> 
>>>>>>> struct trailing_array_1 {
>>>>>>>  int a;
>>>>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>  struct trailing_array_4 *trailing_flex)
>>>>>>> {
>>>>>>>  normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>>>>>  trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>>>  trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>>>> index 8b7db6e4f39..30bb4ca8832 100644
>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>>>> @@ -1,6 +1,6 @@
>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>>>> /* { dg-do compile } */
>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>>>>>> 
>>>>>>> struct trailing_array_1 {
>>>>>>>  int a;
>>>>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>  struct trailing_array_4 *trailing_flex)
>>>>>>> {
>>>>>>>  normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>>>  trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>> 
>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>>>> index 035bf481396..e847a44516e 100644
>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>>>> @@ -1,6 +1,6 @@
>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>>>> /* { dg-do compile } */
>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>>>>>> 
>>>>>>> struct trailing_array_1 {
>>>>>>>  int a;
>>>>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>  struct trailing_array_4 *trailing_flex)
>>>>>>> {
>>>>>>>  normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>>>>>  trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>> 
>>>>>>> }
>>>>>>> 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..2e241f96208
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>>>>>>> @@ -0,0 +1,39 @@
>>>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>>>> +/* { dg-do compile } */
>>>>>>> +/* { 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" } */
>>>>>>> +
>>>>>>> +}
>>>>>>> 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..97eb65ba0a9
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>>>>>>> @@ -0,0 +1,39 @@
>>>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>>>> +/* { dg-do compile } */
>>>>>>> +/* { 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" } */
>>>>>>> +
>>>>>>> +}
>>>>>>> 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..110fdc72778
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>>>>>>> @@ -0,0 +1,39 @@
>>>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>>>> +/* { dg-do compile } */
>>>>>>> +/* { 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" } */
>>>>>>> +
>>>>>>> +}
>>>>>>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
>>>>>>> index 3846dc1d849..e6c6c5a301d 100644
>>>>>>> --- a/gcc/tree-vrp.cc
>>>>>>> +++ b/gcc/tree-vrp.cc
>>>>>>> @@ -1087,7 +1087,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;
>>>>>>> -- 
>>>>>>> 2.31.1
>>>>>>> 
>>>>>> 
>>>>>> 
>>>>> 
>>>>> -- 
>>>>> 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)
>> 
>> 
> 
> -- 
> 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)
  
Qing Zhao Dec. 16, 2022, 5:47 p.m. UTC | #10
FYI.

Committed this last patch as:
https://jira.oci.oraclecorp.com/browse/OLDIS-21095

I will come up with the update to gcc-13/changes.html for -fstrict-flex-arrays very soon.

Thanks.

Qing
> On Dec 16, 2022, at 9:49 AM, Qing Zhao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> 
> 
> 
>> On Dec 16, 2022, at 4:17 AM, Richard Biener <rguenther@suse.de> wrote:
>> 
>> On Thu, 15 Dec 2022, Qing Zhao wrote:
>> 
>>> 
>>> 
>>>> On Dec 15, 2022, at 2:47 AM, Richard Biener <rguenther@suse.de> wrote:
>>>> 
>>>> On Wed, 14 Dec 2022, Qing Zhao wrote:
>>>> 
>>>>> Hi, Richard,
>>>>> 
>>>>> I guess that we now agreed on the following:
>>>>> 
>>>>> “ the information that we ran into a trailing array but didn't consider 
>>>>> it a flex array because of -fstrict-flex-arrays is always a useful information”
>>>>> 
>>>>> The only thing we didn’t decide is:
>>>>> 
>>>>> A. Amend such new information to -Warray-bounds when -fstrict-flex-arrays=N (N>0) specified.
>>>>> 
>>>>> OR
>>>>> 
>>>>> B. Issue such new information with a new warning option -Wstrict-flex-arrays when -fstrict-flex-arrays=N (N>0) specified.
>>>>> 
>>>>> My current patch implemented B. 
>>>> 
>>>> Plus it implements it to specify a different flex-array variant for
>>>> the extra diagnostic.
>>> Could you clarify a little bit on this? (Don’t quite understand…)
>>>> 
>>>>> If you think A is better, I will change the patch as A. 
>>>> 
>>>> I would tend to A since, as I said, it's useful information that
>>>> shouldn't be hidden and not adding an option removes odd combination
>>>> possibilities such as -Wno-array-bounds -Wstrict-flex-arrays.
>>> 
>>> With current implementation, the above combination will ONLY report the 
>>> misuse of trailing array as flex-array.  No out-of-bounds warnings 
>>> issued.
>>> 
>>>> In particular I find, say, -fstrict-flex-arrays=2 -Wstrict-flex-arrays=1
>>>> hardly useful.
>>> 
>>> The above combination will NOT happen, because there is NO level argument for -Wstrict-flex-arrays.
>>> 
>>> The only combination will be:    -fstrict-flex-arrays=N -Wstrict-flex-arrays
>>> 
>>> When N > 0, -Wstrict-flex-arrays will report any misuse of trailing arrays as flexible array per the value of N.
>>>> 
>>>> But I'm interested in other opinions.
>>> 
>>> Adding a separate -Wstrict-flex-arrays will provide users a choice to ONLY look at the mis-use of trailing arrays as flex-arrays.  Without this new option, such information will be buried into tons of out-of-bounds messges. 
>>> 
>>> I think this is the major benefit to have one separate new warning -Wstrict-flex-arrays. 
>>> 
>>> Do we need to provide the users this choice?
>> 
>> Ah, OK - I can see the value of auditing code this way before
>> enabling -fstrict-flex-arrays.
> Yes, I think the major benefit of this option is to help users to identify all the places where the trailing arrays are misused as flex-arrays at different level of -fstrict-flex-arrays=N, then update their source code accordingly. And finally can enable -fstrict-flex-arrays by default.
>> 
>>> +  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");
>> 
>> "is not present”.
> Okay.
>> 
>> The patch is OK with that change.
> Thanks! Will commit the patch after the change.
>> 
>> Thanks and sorry for the slow process ...
> 
> Thank you for your patience and questions.
> The discussion is very helpful since I was not 100% sure whether this new warning is necessary or not in the beginning, but now after this discussion I feel confident that it’s a necessary option to be added.
> 
> Qing
> 
>> 
>> Richard.
>> 
>>> Thanks.
>>> 
>>> Qing
>>>> 
>>>> Thanks,
>>>> Richard.
>>>> 
>>>>> Let me know your opinion.
>>>>> 
>>>>> thanks.
>>>>> 
>>>>> Qing
>>>>> 
>>>>> 
>>>>>> On Dec 14, 2022, at 4:03 AM, Richard Biener <rguenther@suse.de> wrote:
>>>>>> 
>>>>>> On Tue, 13 Dec 2022, Qing Zhao wrote:
>>>>>> 
>>>>>>> Richard, 
>>>>>>> 
>>>>>>> Do you have any decision on this one? 
>>>>>>> Do we need this warning option For GCC? 
>>>>>> 
>>>>>> Looking at the testcases it seems that the diagnostic amends
>>>>>> -Warray-bounds diagnostics for trailing but not flexible arrays?
>>>>>> Wouldn't it be better to generally diagnose this, so have
>>>>>> -Warray-bounds, with -fstrict-flex-arrays, for
>>>>>> 
>>>>>> struct X { int a[1]; };
>>>>>> int foo (struct X *p)
>>>>>> {
>>>>>> return p->a[1];
>>>>>> }
>>>>>> 
>>>>>> emit
>>>>>> 
>>>>>> warning: array subscript 1 is above array bounds ...
>>>>>> note: the trailing array is only a flexible array member with 
>>>>>> -fno-strict-flex-arrays
>>>>>> 
>>>>>> ?  Having -Wstrict-flex-arrays=N and N not agree with the
>>>>>> -fstrict-flex-arrays level sounds hardly useful to me but the
>>>>>> information that we ran into a trailing array but didn't consider
>>>>>> it a flex array because of -fstrict-flex-arrays is always a
>>>>>> useful information?
>>>>>> 
>>>>>> But maybe I misunderstood this new diagnostic?
>>>>>> 
>>>>>> Thanks,
>>>>>> Richard.
>>>>>> 
>>>>>> 
>>>>>>> thanks.
>>>>>>> 
>>>>>>> Qing
>>>>>>> 
>>>>>>>> On Dec 6, 2022, at 11:18 AM, Qing Zhao <qing.zhao@oracle.com> 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.
>>>>>>>> 
>>>>>>>> gcc/ChangeLog:
>>>>>>>> 
>>>>>>>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option.
>>>>>>>> 	* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add two more
>>>>>>>> 	arguments.
>>>>>>>> 	(array_bounds_checker::check_array_ref): Issue warnings for
>>>>>>>> 	-Wstrict-flex-arrays.
>>>>>>>> 	* opts.cc (finish_options): Issue warning for unsupported combination
>>>>>>>> 	of -Wstrict_flex_arrays and -fstrict-flex-array.
>>>>>>>> 	* tree-vrp.cc (execute_ranger_vrp): Enable the pass when
>>>>>>>> 	warn_strict_flex_array is true.
>>>>>>>> 
>>>>>>>> gcc/c-family/ChangeLog:
>>>>>>>> 
>>>>>>>> 	* c.opt (Wstrict-flex-arrays): New option.
>>>>>>>> 
>>>>>>>> gcc/testsuite/ChangeLog:
>>>>>>>> 
>>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-1.c: Update testing case with
>>>>>>>> 	-Wstrict-flex-arrays.
>>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-2.c: Likewise.
>>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-3.c: Likewise.
>>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-4.c: Likewise.
>>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-5.c: Likewise.
>>>>>>>> 	* gcc.dg/Warray-bounds-flex-arrays-6.c: Likewise.
>>>>>>>> 	* c-c++-common/Wstrict-flex-arrays.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.c: New test.
>>>>>>>> ---
>>>>>>>> gcc/c-family/c.opt                            |   5 +
>>>>>>>> gcc/doc/invoke.texi                           |  27 ++++-
>>>>>>>> gcc/gimple-array-bounds.cc                    | 103 ++++++++++++++----
>>>>>>>> gcc/opts.cc                                   |   8 ++
>>>>>>>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 ++
>>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-1.c      |   5 +-
>>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-2.c      |   6 +-
>>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-3.c      |   7 +-
>>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-4.c      |   5 +-
>>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-5.c      |   6 +-
>>>>>>>> .../gcc.dg/Warray-bounds-flex-arrays-6.c      |   7 +-
>>>>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  39 +++++++
>>>>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  39 +++++++
>>>>>>>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  39 +++++++
>>>>>>>> gcc/tree-vrp.cc                               |   2 +-
>>>>>>>> 15 files changed, 273 insertions(+), 34 deletions(-)
>>>>>>>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.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.c
>>>>>>>> 
>>>>>>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>>>>>>> index 0d0ad0a6374..33edeefd285 100644
>>>>>>>> --- a/gcc/c-family/c.opt
>>>>>>>> +++ b/gcc/c-family/c.opt
>>>>>>>> @@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
>>>>>>>> index 726392409b6..4402b0427ef 100644
>>>>>>>> --- a/gcc/doc/invoke.texi
>>>>>>>> +++ b/gcc/doc/invoke.texi
>>>>>>>> @@ -398,7 +398,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
>>>>>>>> @@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
>>>>>>>> --- a/gcc/gimple-array-bounds.cc
>>>>>>>> +++ b/gcc/gimple-array-bounds.cc
>>>>>>>> @@ -252,25 +252,34 @@ get_up_bounds_for_array_ref (tree ref, tree *decl,
>>>>>>>> 
>>>>>>>> /* 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.
>>>>>>>> -   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
>>>>>>>> +   When out of bounds, set OUT_OF_BOUND to true.
>>>>>>>> +   Issue warnings if FOR_ARRAY_BOUND is true.
>>>>>>>> +   return TRUE if warnings are issued.  */
>>>>>>>> +
>>>>>>>> 
>>>>>>>> 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 ignore_off_by_one, bool for_array_bound,
>>>>>>>> +			      bool *out_of_bound)
>>>>>>>> {
>>>>>>>> tree low_bound = array_ref_low_bound (ref);
>>>>>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>>>>>> 
>>>>>>>> bool warned = false;
>>>>>>>> +  *out_of_bound = 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_org, artype);
>>>>>>>> +    {
>>>>>>>> +      *out_of_bound = true;
>>>>>>>> +      if (for_array_bound)
>>>>>>>> +	warned = warning_at (location, OPT_Warray_bounds_,
>>>>>>>> +			     "array subscript %E is outside array"
>>>>>>>> +			     " bounds of %qT", low_sub_org, artype);
>>>>>>>> +    }
>>>>>>>> 
>>>>>>>> if (warned)
>>>>>>>> ; /* Do nothing.  */
>>>>>>>> @@ -283,24 +292,33 @@ check_out_of_bounds_and_warn (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);
>>>>>>>> +	{
>>>>>>>> +	  *out_of_bound = true;
>>>>>>>> +	  warned = warning_at (location, OPT_Warray_bounds_,
>>>>>>>> +			       "array subscript [%E, %E] is outside "
>>>>>>>> +			       "array bounds of %qT",
>>>>>>>> +			       low_sub, up_sub, artype);
>>>>>>>> +	}
>>>>>>>> }
>>>>>>>> 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);
>>>>>>>> +    {
>>>>>>>> +      *out_of_bound = true;
>>>>>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>>>>>>> +			   "array subscript %E is above array bounds of %qT",
>>>>>>>> +			   up_sub, artype);
>>>>>>>> +    }
>>>>>>>> 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);
>>>>>>>> +    {
>>>>>>>> +      *out_of_bound = true;
>>>>>>>> +      warned = warning_at (location, OPT_Warray_bounds_,
>>>>>>>> +			   "array subscript %E is below array bounds of %qT",
>>>>>>>> +			   low_sub, artype);
>>>>>>>> +    }
>>>>>>>> return warned;
>>>>>>>> }
>>>>>>>> 
>>>>>>>> @@ -333,14 +351,21 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>>>>>> 
>>>>>>>> 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);
>>>>>>>> +    {
>>>>>>>> +      /* 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);
>>>>>>>> +    }
>>>>>>>> 
>>>>>>>> get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
>>>>>>>> 
>>>>>>>> bool warned = false;
>>>>>>>> +  bool out_of_bound = false;
>>>>>>>> 
>>>>>>>> tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>>>>>>>> tree low_sub_org = TREE_OPERAND (ref, 1);
>>>>>>>> @@ -361,7 +386,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>>>>>>> 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);
>>>>>>>> +					 ignore_off_by_one, warn_array_bounds,
>>>>>>>> +					 &out_of_bound);
>>>>>>>> 
>>>>>>>> 
>>>>>>>> if (!warned && sam == special_array_member::int_0)
>>>>>>>> @@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
>>>>>>>> --- a/gcc/opts.cc
>>>>>>>> +++ b/gcc/opts.cc
>>>>>>>> @@ -1411,6 +1411,14 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
>>>>>>>>   opts->x_profile_flag = 0;
>>>>>>>> }
>>>>>>>> 
>>>>>>>> +  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>>>>> index d36ba4d86cb..65c9fec43af 100644
>>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
>>>>>>>> @@ -1,6 +1,6 @@
>>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>>>>> /* { dg-do compile} */
>>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
>>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
>>>>>>>> 
>>>>>>>> struct trailing_array_1 {
>>>>>>>> int a;
>>>>>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>> struct trailing_array_4 *trailing_flex)
>>>>>>>> {
>>>>>>>> normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>>>>>> trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>>>> trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>>>>> index f63206e1948..2b5a895c598 100644
>>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
>>>>>>>> @@ -1,6 +1,6 @@
>>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>>>>> /* { dg-do compile } */
>>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
>>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
>>>>>>>> 
>>>>>>>> struct trailing_array_1 {
>>>>>>>> int a;
>>>>>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>> struct trailing_array_4 *trailing_flex)
>>>>>>>> {
>>>>>>>> normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
>>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>>>> trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>>> 
>>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>>>>> index e3273714e8b..25b903f2615 100644
>>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
>>>>>>>> @@ -1,6 +1,6 @@
>>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds.  */
>>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
>>>>>>>> /* { dg-do compile } */
>>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
>>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
>>>>>>>> 
>>>>>>>> struct trailing_array_1 {
>>>>>>>> int a;
>>>>>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>> struct trailing_array_4 *trailing_flex)
>>>>>>>> {
>>>>>>>> normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
>>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
>>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
>>>>>>>> 
>>>>>>>> }
>>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>>>>> index cabaea77dc2..5fc500a19ca 100644
>>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
>>>>>>>> @@ -1,6 +1,6 @@
>>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>>>>> /* { dg-do compile } */
>>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>>>>>>>> 
>>>>>>>> struct trailing_array_1 {
>>>>>>>> int a;
>>>>>>>> @@ -32,6 +32,7 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>> struct trailing_array_4 *trailing_flex)
>>>>>>>> {
>>>>>>>> normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
>>>>>>>> trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>>>> trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>>>>> index 8b7db6e4f39..30bb4ca8832 100644
>>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
>>>>>>>> @@ -1,6 +1,6 @@
>>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>>>>> /* { dg-do compile } */
>>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>>>>>>>> 
>>>>>>>> struct trailing_array_1 {
>>>>>>>> int a;
>>>>>>>> @@ -32,7 +32,9 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>> struct trailing_array_4 *trailing_flex)
>>>>>>>> {
>>>>>>>> normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
>>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
>>>>>>>> trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>>> 
>>>>>>>> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>>>>> index 035bf481396..e847a44516e 100644
>>>>>>>> --- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
>>>>>>>> @@ -1,6 +1,6 @@
>>>>>>>> -/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
>>>>>>>> +/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
>>>>>>>> /* { dg-do compile } */
>>>>>>>> -/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>>>>>>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>>>>>>>> 
>>>>>>>> struct trailing_array_1 {
>>>>>>>> int a;
>>>>>>>> @@ -32,8 +32,11 @@ void __attribute__((__noinline__)) stuff(
>>>>>>>> struct trailing_array_4 *trailing_flex)
>>>>>>>> {
>>>>>>>> normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
>>>>>>>> +    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
>>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
>>>>>>>> +    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
>>>>>>>> trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
>>>>>>>> 
>>>>>>>> }
>>>>>>>> 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..2e241f96208
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>>>>>>>> @@ -0,0 +1,39 @@
>>>>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>>>>> +/* { dg-do compile } */
>>>>>>>> +/* { 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" } */
>>>>>>>> +
>>>>>>>> +}
>>>>>>>> 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..97eb65ba0a9
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>>>>>>>> @@ -0,0 +1,39 @@
>>>>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>>>>> +/* { dg-do compile } */
>>>>>>>> +/* { 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" } */
>>>>>>>> +
>>>>>>>> +}
>>>>>>>> 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..110fdc72778
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>>>>>>>> @@ -0,0 +1,39 @@
>>>>>>>> +/* Test -Wstrict-flex-arrays.  */
>>>>>>>> +/* { dg-do compile } */
>>>>>>>> +/* { 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" } */
>>>>>>>> +
>>>>>>>> +}
>>>>>>>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
>>>>>>>> index 3846dc1d849..e6c6c5a301d 100644
>>>>>>>> --- a/gcc/tree-vrp.cc
>>>>>>>> +++ b/gcc/tree-vrp.cc
>>>>>>>> @@ -1087,7 +1087,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;
>>>>>>>> -- 
>>>>>>>> 2.31.1
>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>>> -- 
>>>>>> 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)
>>> 
>>> 
>> 
>> -- 
>> 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)
  

Patch

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 0d0ad0a6374..33edeefd285 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -976,6 +976,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/doc/invoke.texi b/gcc/doc/invoke.texi
index 726392409b6..4402b0427ef 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -398,7 +398,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
@@ -7835,6 +7835,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 db3459af325..825f11331b5 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -252,25 +252,34 @@  get_up_bounds_for_array_ref (tree ref, tree *decl,
 
 /* 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.
-   Issue warnings if out of bound, return TRUE if warnings are issued.  */ 
+   When out of bounds, set OUT_OF_BOUND to true.
+   Issue warnings if FOR_ARRAY_BOUND is true.
+   return TRUE if warnings are issued.  */
+
 
 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 ignore_off_by_one, bool for_array_bound,
+			      bool *out_of_bound)
 {
   tree low_bound = array_ref_low_bound (ref);
   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
 
   bool warned = false;
+  *out_of_bound = 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_org, artype);
+    {
+      *out_of_bound = true;
+      if (for_array_bound)
+	warned = warning_at (location, OPT_Warray_bounds_,
+			     "array subscript %E is outside array"
+			     " bounds of %qT", low_sub_org, artype);
+    }
 
   if (warned)
     ; /* Do nothing.  */
@@ -283,24 +292,33 @@  check_out_of_bounds_and_warn (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);
+	{
+	  *out_of_bound = true;
+	  warned = warning_at (location, OPT_Warray_bounds_,
+			       "array subscript [%E, %E] is outside "
+			       "array bounds of %qT",
+			       low_sub, up_sub, artype);
+	}
     }
   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);
+    {
+      *out_of_bound = true;
+      warned = warning_at (location, OPT_Warray_bounds_,
+			   "array subscript %E is above array bounds of %qT",
+			   up_sub, artype);
+    }
   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);
+    {
+      *out_of_bound = true;
+      warned = warning_at (location, OPT_Warray_bounds_,
+			   "array subscript %E is below array bounds of %qT",
+			   low_sub, artype);
+    }
   return warned;
 }
 
@@ -333,14 +351,21 @@  array_bounds_checker::check_array_ref (location_t location, tree ref,
 
   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);
+    {
+      /* 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);
+    }
 
   get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);
 
   bool warned = false;
+  bool out_of_bound = false;
 
   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
   tree low_sub_org = TREE_OPERAND (ref, 1);
@@ -361,7 +386,8 @@  array_bounds_checker::check_array_ref (location_t location, tree ref,
   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);
+					 ignore_off_by_one, warn_array_bounds,
+					 &out_of_bound);
 
 
   if (!warned && sam == special_array_member::int_0)
@@ -373,19 +399,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 73fc97756e4..8db53ad6c77 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -1411,6 +1411,14 @@  finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
       opts->x_profile_flag = 0;
     }
 
+  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/gcc.dg/Warray-bounds-flex-arrays-1.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
index d36ba4d86cb..65c9fec43af 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-1.c
@@ -1,6 +1,6 @@ 
-/* Test -fstrict-flex-arrays + -Warray-bounds.  */
+/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
 /* { dg-do compile} */
-/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds" } */
+/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
 
 struct trailing_array_1 {
     int a;
@@ -32,6 +32,7 @@  void __attribute__((__noinline__)) stuff(
     struct trailing_array_4 *trailing_flex)
 {
     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
+    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
     trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
index f63206e1948..2b5a895c598 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-2.c
@@ -1,6 +1,6 @@ 
-/* Test -fstrict-flex-arrays + -Warray-bounds.  */
+/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
 /* { dg-do compile } */
-/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds" } */
+/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
 
 struct trailing_array_1 {
     int a;
@@ -32,7 +32,9 @@  void __attribute__((__noinline__)) stuff(
     struct trailing_array_4 *trailing_flex)
 {
     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
+    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
     trailing_1->c[2] = 2; /* { dg-warning "array subscript 2 is above array bounds of"  } */
+    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
 
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
index e3273714e8b..25b903f2615 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-3.c
@@ -1,6 +1,6 @@ 
-/* Test -fstrict-flex-arrays + -Warray-bounds.  */
+/* Test -fstrict-flex-arrays + -Warray-bounds + -Wstrict-flex-arrays.  */
 /* { dg-do compile } */
-/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds" } */
+/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
 
 struct trailing_array_1 {
     int a;
@@ -32,8 +32,11 @@  void __attribute__((__noinline__)) stuff(
     struct trailing_array_4 *trailing_flex)
 {
     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
+    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */ 
+    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
     trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */ 
+    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript" } */
 
 }
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
index cabaea77dc2..5fc500a19ca 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-4.c
@@ -1,6 +1,6 @@ 
-/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
+/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
 /* { dg-do compile } */
-/* { dg-options "-O2 -fstrict-flex-arrays=1 -Warray-bounds=2" } */
+/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
 
 struct trailing_array_1 {
     int a;
@@ -32,6 +32,7 @@  void __attribute__((__noinline__)) stuff(
     struct trailing_array_4 *trailing_flex)
 {
     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */
+    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
     trailing_1->c[2] = 2; /* { dg-bogus "array subscript " } */
     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
index 8b7db6e4f39..30bb4ca8832 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-5.c
@@ -1,6 +1,6 @@ 
-/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
+/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
 /* { dg-do compile } */
-/* { dg-options "-O2 -fstrict-flex-arrays=2 -Warray-bounds=2" } */
+/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
 
 struct trailing_array_1 {
     int a;
@@ -32,7 +32,9 @@  void __attribute__((__noinline__)) stuff(
     struct trailing_array_4 *trailing_flex)
 {
     normal->c[5] = 5;   /*{ dg-warning "array subscript 5 is above array bounds of" } */
+    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
+    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
     trailing_0->c[1] = 1; /* { dg-bogus "array subscript " } */
     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
 
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
index 035bf481396..e847a44516e 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-flex-arrays-6.c
@@ -1,6 +1,6 @@ 
-/* Test -fstrict-flex-arrays + -Warray-bounds=2.  */
+/* Test -fstrict-flex-arrays + -Warray-bounds=2 + -Wstrict-flex-arrays.  */
 /* { dg-do compile } */
-/* { dg-options "-O2 -fstrict-flex-arrays=3 -Warray-bounds=2" } */
+/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
 
 struct trailing_array_1 {
     int a;
@@ -32,8 +32,11 @@  void __attribute__((__noinline__)) stuff(
     struct trailing_array_4 *trailing_flex)
 {
     normal->c[5] = 5; 	/*{ dg-warning "array subscript 5 is above array bounds of" } */ 
+    			/*{ dg-warning "should not be used as a flexible array member for level 1 and above" "" { target *-*-* } .-1 } */
     trailing_1->c[2] = 2; /*{ dg-warning "array subscript 2 is above array bounds of" } */
+    			  /* { dg-warning "should not be used as a flexible array member for level 2 and above" "" { target *-*-* } .-1 } */
     trailing_0->c[1] = 1; /*{ dg-warning "array subscript 1 is outside array bounds of" } */
+    			  /* { dg-warning "should not be used as a flexible array member for level 3" "" { target *-*-* } .-1 } */
     trailing_flex->c[10] = 10; /* { dg-bogus "array subscript " } */
 
 }
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..2e241f96208
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
@@ -0,0 +1,39 @@ 
+/* Test -Wstrict-flex-arrays.  */
+/* { dg-do compile } */
+/* { 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" } */
+
+}
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..97eb65ba0a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
@@ -0,0 +1,39 @@ 
+/* Test -Wstrict-flex-arrays.  */
+/* { dg-do compile } */
+/* { 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" } */
+
+}
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..110fdc72778
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
@@ -0,0 +1,39 @@ 
+/* Test -Wstrict-flex-arrays.  */
+/* { dg-do compile } */
+/* { 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" } */
+
+}
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index 3846dc1d849..e6c6c5a301d 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -1087,7 +1087,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;