[V3,2/2] Add a new warning option -Wstrict-flex-arrays.
Checks
Commit Message
'-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
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
>
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
> >
>
>
> 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)
> 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)
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)
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)
>
>
> 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)
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)
>
>
> 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)
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)
@@ -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.
@@ -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=
@@ -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;
@@ -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);
}
new file mode 100644
@@ -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 } */
@@ -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 " } */
@@ -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 " } */
@@ -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" } */
}
@@ -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 " } */
@@ -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 " } */
@@ -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 " } */
}
new file mode 100644
@@ -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" } */
+
+}
new file mode 100644
@@ -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" } */
+
+}
new file mode 100644
@@ -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" } */
+
+}
@@ -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;