diff options
author | Qing Zhao <qing.zhao@oracle.com> | 2022-12-16 17:25:42 +0000 |
---|---|---|
committer | Qing Zhao <qing.zhao@oracle.com> | 2022-12-16 17:25:42 +0000 |
commit | 2a27ae32fabf85685ffff758459d7ec284ccb95a (patch) | |
tree | f454c76a179f030d6b89947de1c233d6934dc7d3 /gcc/gimple-array-bounds.cc | |
parent | 9bb7864877ab05bf951fad66c934845351b271ce (diff) | |
download | gcc-2a27ae32fabf85685ffff758459d7ec284ccb95a.zip gcc-2a27ae32fabf85685ffff758459d7ec284ccb95a.tar.gz gcc-2a27ae32fabf85685ffff758459d7ec284ccb95a.tar.bz2 |
Add a new warning option -Wstrict-flex-arrays.
'-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.
Diffstat (limited to 'gcc/gimple-array-bounds.cc')
-rw-r--r-- | gcc/gimple-array-bounds.cc | 105 |
1 files changed, 85 insertions, 20 deletions
diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index 59bd9eb..9fd42fe 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -252,25 +252,33 @@ 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 +291,36 @@ 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; + if (for_array_bound) + warned = warning_at (location, OPT_Warray_bounds_, + "array subscript [%E, %E] is outside " + "array bounds of %qT", + low_sub, up_sub, artype); + } } else 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; + if (for_array_bound) + 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; + if (for_array_bound) + warned = warning_at (location, OPT_Warray_bounds_, + "array subscript %E is below array bounds of %qT", + low_sub, artype); + } return warned; } @@ -333,14 +353,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 +388,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 +401,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; |