aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.cc
diff options
context:
space:
mode:
authorQing Zhao <qing.zhao@oracle.com>2022-12-06 18:50:04 +0000
committerQing Zhao <qing.zhao@oracle.com>2022-12-06 18:50:04 +0000
commit710c9676520dfd38b4bfdcc937ce026ed89921d6 (patch)
tree81a6bc70c710cba93ab79a61180ce822fe31ae13 /gcc/tree.cc
parentdcfc7ac94dbcf6c86c0c58ce6dc1d8bd853e4093 (diff)
downloadgcc-710c9676520dfd38b4bfdcc937ce026ed89921d6.zip
gcc-710c9676520dfd38b4bfdcc937ce026ed89921d6.tar.gz
gcc-710c9676520dfd38b4bfdcc937ce026ed89921d6.tar.bz2
Update -Warray-bounds with -fstrict-flex-arrays.
A. add the following to clarify the relationship between -Warray-bounds and the LEVEL of -fstrict-flex-array: By default, the trailing array of a structure will be treated as a flexible array member by '-Warray-bounds' or '-Warray-bounds=N' if it is declared as either a flexible array member per C99 standard onwards ('[]'), a GCC zero-length array extension ('[0]'), or an one-element array ('[1]'). As a result, out of bounds subscripts or offsets into zero-length arrays or one-element arrays are not warned by default. You can add the option '-fstrict-flex-arrays' or '-fstrict-flex-arrays=LEVEL' to control how this option treat trailing array of a structure as a flexible array member. when LEVEL<=1, no change to the default behavior. when LEVEL=2, additional warnings will be issued for out of bounds subscripts or offsets into one-element arrays; when LEVEL=3, in addition to LEVEL=2, additional warnings will be issued for out of bounds subscripts or offsets into zero-length arrays. B. change -Warray-bounds=2 to exclude its control on how to treat trailing arrays as flexible array members: '-Warray-bounds=2' This warning level also warns about the intermediate results of pointer arithmetic that may yield out of bounds values. This warning level may give a larger number of false positives and is deactivated by default. gcc/ChangeLog: * attribs.cc (strict_flex_array_level_of): New function. * attribs.h (strict_flex_array_level_of): Prototype for new function. * doc/invoke.texi: Update -Warray-bounds by specifying the impact from -fstrict-flex-arrays. Also update -Warray-bounds=2 by eliminating its impact on treating trailing arrays as flexible array members. * gimple-array-bounds.cc (get_up_bounds_for_array_ref): New function. (check_out_of_bounds_and_warn): New function. (array_bounds_checker::check_array_ref): Update with call to the above new functions. * tree.cc (array_ref_flexible_size_p): Add one new argument. (component_ref_sam_type): New function. (component_ref_size): Control with level of strict-flex-array. * tree.h (array_ref_flexible_size_p): Update prototype. (enum struct special_array_member): Add two new enum values. (component_ref_sam_type): New prototype. gcc/c/ChangeLog: * c-decl.cc (is_flexible_array_member_p): Call new function strict_flex_array_level_of. gcc/testsuite/ChangeLog: * gcc.dg/Warray-bounds-11.c: Update warnings for -Warray-bounds=2. * gcc.dg/Warray-bounds-flex-arrays-1.c: New test. * gcc.dg/Warray-bounds-flex-arrays-2.c: New test. * gcc.dg/Warray-bounds-flex-arrays-3.c: New test. * gcc.dg/Warray-bounds-flex-arrays-4.c: New test. * gcc.dg/Warray-bounds-flex-arrays-5.c: New test. * gcc.dg/Warray-bounds-flex-arrays-6.c: New test.
Diffstat (limited to 'gcc/tree.cc')
-rw-r--r--gcc/tree.cc159
1 files changed, 118 insertions, 41 deletions
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 254b237..b40c95a 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -12719,15 +12719,21 @@ array_ref_up_bound (tree exp)
int test (uint8_t *p, uint32_t t[1][1], int n) {
for (int i = 0; i < 4; i++, p++)
t[i][0] = ...;
+
+ If non-null, set IS_TRAILING_ARRAY to true if the ref is the above case A.
*/
bool
-array_ref_flexible_size_p (tree ref)
+array_ref_flexible_size_p (tree ref, bool *is_trailing_array /* = NULL */)
{
- /* the TYPE for this array referece. */
+ /* The TYPE for this array referece. */
tree atype = NULL_TREE;
- /* the FIELD_DECL for the array field in the containing structure. */
+ /* The FIELD_DECL for the array field in the containing structure. */
tree afield_decl = NULL_TREE;
+ /* Whether this array is the trailing array of a structure. */
+ bool is_trailing_array_tmp = false;
+ if (!is_trailing_array)
+ is_trailing_array = &is_trailing_array_tmp;
if (TREE_CODE (ref) == ARRAY_REF
|| TREE_CODE (ref) == ARRAY_RANGE_REF)
@@ -12815,7 +12821,10 @@ array_ref_flexible_size_p (tree ref)
if (! TYPE_SIZE (atype)
|| ! TYPE_DOMAIN (atype)
|| ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
- return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
+ {
+ *is_trailing_array = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
+ return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
+ }
/* If the reference is based on a declared entity, the size of the array
is constrained by its given domain. (Do not trust commons PR/69368). */
@@ -12837,9 +12846,17 @@ array_ref_flexible_size_p (tree ref)
if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (atype))) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST
|| TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST)
- return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
+ {
+ *is_trailing_array
+ = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
+ return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
+ }
if (! get_addr_base_and_unit_offset (ref_to_array, &offset))
- return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
+ {
+ *is_trailing_array
+ = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
+ return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
+ }
/* If at least one extra element fits it is a flexarray. */
if (known_le ((wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
@@ -12847,11 +12864,16 @@ array_ref_flexible_size_p (tree ref)
+ 2)
* wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (atype))),
wi::to_offset (DECL_SIZE_UNIT (ref)) - offset))
- return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
+ {
+ *is_trailing_array
+ = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
+ return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
+ }
return false;
}
+ *is_trailing_array = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
}
@@ -12913,11 +12935,63 @@ get_initializer_for (tree init, tree decl)
return NULL_TREE;
}
+/* Determines the special array member type for the array reference REF. */
+special_array_member
+component_ref_sam_type (tree ref)
+{
+ special_array_member sam_type = special_array_member::none;
+
+ tree member = TREE_OPERAND (ref, 1);
+ tree memsize = DECL_SIZE_UNIT (member);
+ if (memsize)
+ {
+ tree memtype = TREE_TYPE (member);
+ if (TREE_CODE (memtype) != ARRAY_TYPE)
+ return sam_type;
+
+ bool trailing = false;
+ (void)array_ref_flexible_size_p (ref, &trailing);
+ bool zero_length = integer_zerop (memsize);
+ if (!trailing && !zero_length)
+ /* MEMBER is an interior array with
+ more than one element. */
+ return special_array_member::int_n;
+
+ if (zero_length)
+ {
+ if (trailing)
+ return special_array_member::trail_0;
+ else
+ return special_array_member::int_0;
+ }
+
+ if (!zero_length)
+ if (tree dom = TYPE_DOMAIN (memtype))
+ if (tree min = TYPE_MIN_VALUE (dom))
+ if (tree max = TYPE_MAX_VALUE (dom))
+ if (TREE_CODE (min) == INTEGER_CST
+ && TREE_CODE (max) == INTEGER_CST)
+ {
+ offset_int minidx = wi::to_offset (min);
+ offset_int maxidx = wi::to_offset (max);
+ offset_int neltsm1 = maxidx - minidx;
+ if (neltsm1 > 0)
+ /* MEMBER is a trailing array with more than
+ one elements. */
+ return special_array_member::trail_n;
+
+ if (neltsm1 == 0)
+ return special_array_member::trail_1;
+ }
+ }
+
+ return sam_type;
+}
+
/* Determines the size of the member referenced by the COMPONENT_REF
REF, using its initializer expression if necessary in order to
determine the size of an initialized flexible array member.
- If non-null, set *ARK when REF refers to an interior zero-length
- array or a trailing one-element array.
+ If non-null, set *SAM to the type of special array member.
Returns the size as sizetype (which might be zero for an object
with an uninitialized flexible array member) or null if the size
cannot be determined. */
@@ -12930,7 +13004,7 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
special_array_member sambuf;
if (!sam)
sam = &sambuf;
- *sam = special_array_member::none;
+ *sam = component_ref_sam_type (ref);
/* The object/argument referenced by the COMPONENT_REF and its type. */
tree arg = TREE_OPERAND (ref, 0);
@@ -12951,43 +13025,46 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
return (tree_int_cst_equal (memsize, TYPE_SIZE_UNIT (memtype))
? memsize : NULL_TREE);
- bool trailing = array_ref_flexible_size_p (ref);
- bool zero_length = integer_zerop (memsize);
- if (!trailing && !zero_length)
- /* MEMBER is either an interior array or is an array with
- more than one element. */
+ /* 2-or-more elements arrays are treated as normal arrays by default. */
+ if (*sam == special_array_member::int_n
+ || *sam == special_array_member::trail_n)
return memsize;
- if (zero_length)
+ /* flag_strict_flex_arrays will control how to treat
+ the trailing arrays as flexiable array members. */
+
+ tree afield_decl = TREE_OPERAND (ref, 1);
+ unsigned int strict_flex_array_level
+ = strict_flex_array_level_of (afield_decl);
+
+ switch (strict_flex_array_level)
{
- if (trailing)
- *sam = special_array_member::trail_0;
- else
- {
- *sam = special_array_member::int_0;
- memsize = NULL_TREE;
- }
+ case 3:
+ /* Treaing 0-length trailing arrays as normal array. */
+ if (*sam == special_array_member::trail_0)
+ return size_zero_node;
+ /* FALLTHROUGH. */
+ case 2:
+ /* Treating 1-element trailing arrays as normal array. */
+ if (*sam == special_array_member::trail_1)
+ return memsize;
+ /* FALLTHROUGH. */
+ case 1:
+ /* Treating 2-or-more elements trailing arrays as normal
+ array. */
+ if (*sam == special_array_member::trail_n)
+ return memsize;
+ /* FALLTHROUGH. */
+ case 0:
+ break;
+ default:
+ gcc_unreachable ();
}
- if (!zero_length)
- if (tree dom = TYPE_DOMAIN (memtype))
- if (tree min = TYPE_MIN_VALUE (dom))
- if (tree max = TYPE_MAX_VALUE (dom))
- if (TREE_CODE (min) == INTEGER_CST
- && TREE_CODE (max) == INTEGER_CST)
- {
- offset_int minidx = wi::to_offset (min);
- offset_int maxidx = wi::to_offset (max);
- offset_int neltsm1 = maxidx - minidx;
- if (neltsm1 > 0)
- /* MEMBER is an array with more than one element. */
- return memsize;
-
- if (neltsm1 == 0)
- *sam = special_array_member::trail_1;
- }
+ if (*sam == special_array_member::int_0)
+ memsize = NULL_TREE;
- /* For a reference to a zero- or one-element array member of a union
+ /* For a reference to a flexible array member of a union
use the size of the union instead of the size of the member. */
if (TREE_CODE (argtype) == UNION_TYPE)
memsize = TYPE_SIZE_UNIT (argtype);