aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.cc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-03-21 11:06:20 +0100
committerJakub Jelinek <jakub@redhat.com>2023-03-21 11:06:20 +0100
commit03041e0361cbdd7f541f2f39060759aad866ed58 (patch)
treeeb6ed004893ae83f1b0fbc80296d8eabb2b75d59 /gcc/tree.cc
parent0395e1364dd969e5845d4b9198e6f8c28b297d36 (diff)
downloadgcc-03041e0361cbdd7f541f2f39060759aad866ed58.zip
gcc-03041e0361cbdd7f541f2f39060759aad866ed58.tar.gz
gcc-03041e0361cbdd7f541f2f39060759aad866ed58.tar.bz2
tree: Fix up component_ref_sam_type handling of arrays of 0 sized elements [PR109215]
Our documentation sadly talks about elt_type arr[0]; as zero-length arrays, not arrays with zero elements. Unfortunately, those aren't the only arrays which can have zero size, the same size can be also result of zero-length element, like in GNU C struct whatever {} or in GNU C/C++ if the element type is [0] array or combination thereof (dunno if Ada doesn't allow something similar too). One can't do much with them, taking address of their elements, (no-op) copying of the elements in and out. But they behave differently from arr[0] arrays e.g. in that using non-zero indexes in them (as long as they are within bounds as for normal arrays) is valid. I think this naming inaccuracy resulted in Martin designing special_array_member in an inconsistent way, mixing size zero array members with array members of one or two or more elements and then using the size zero interchangeably with zero elements. The following patch changes that (but doesn't do any documentation/diagnostics renaming, as this is really a corner case), such that int_0/trail_0 for consistency is just about [0] arrays plus [] for the latter, not one or more zero sized elements case. The testcase has one xfailed case for where perhaps in later GCC versions we could add extra code to handle it, for some reason we don't diagnose out of bounds accesses for the zero sized elements cases. It will be harder because e.g. FRE will canonicalize &var.fld[0] and &var.fld[10] to just one of them because they are provably the same address. But the important thing is to fix this regression (where we warn on completely valid code in the Linux kernel). Anyway, for further work on this we don't really need any extra help from special_array_member, all code can just check integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (type))), it doesn't depend on the position of the members etc. 2023-03-21 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/109215 * tree.h (enum special_array_member): Adjust comments for int_0 and trail_0. * tree.cc (component_ref_sam_type): Clear zero_elts if memtype has zero sized element type and the array has variable number of elements or constant one or more elements. (component_ref_size): Adjust comments, formatting fix. * gcc.dg/Wzero-length-array-bounds-3.c: New test.
Diffstat (limited to 'gcc/tree.cc')
-rw-r--r--gcc/tree.cc33
1 files changed, 23 insertions, 10 deletions
diff --git a/gcc/tree.cc b/gcc/tree.cc
index d17106e..207293c 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -13032,14 +13032,27 @@ component_ref_sam_type (tree ref)
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. */
+ (void) array_ref_flexible_size_p (ref, &trailing);
+ bool zero_elts = integer_zerop (memsize);
+ if (zero_elts && integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (memtype))))
+ {
+ /* If array element has zero size, verify if it is a flexible
+ array member or zero length array. Clear zero_elts if
+ it has one or more members or is a VLA member. */
+ 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
+ || !((integer_zerop (min) && integer_all_onesp (max))
+ || tree_int_cst_lt (max, min)))
+ zero_elts = false;
+ }
+ if (!trailing && !zero_elts)
+ /* MEMBER is an interior array with more than one element. */
return special_array_member::int_n;
- if (zero_length)
+ if (zero_elts)
{
if (trailing)
return special_array_member::trail_0;
@@ -13047,7 +13060,7 @@ component_ref_sam_type (tree ref)
return special_array_member::int_0;
}
- if (!zero_length)
+ if (!zero_elts)
if (tree dom = TYPE_DOMAIN (memtype))
if (tree min = TYPE_MIN_VALUE (dom))
if (tree max = TYPE_MAX_VALUE (dom))
@@ -13114,14 +13127,14 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
tree afield_decl = TREE_OPERAND (ref, 1);
gcc_assert (TREE_CODE (afield_decl) == FIELD_DECL);
- /* if the trailing array is a not a flexible array member, treat it as
+ /* If the trailing array is a not a flexible array member, treat it as
a normal array. */
if (DECL_NOT_FLEXARRAY (afield_decl)
&& *sam != special_array_member::int_0)
return memsize;
if (*sam == special_array_member::int_0)
- memsize = NULL_TREE;
+ memsize = NULL_TREE;
/* For a reference to a flexible array member of a union
use the size of the union instead of the size of the member. */
@@ -13129,7 +13142,7 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
memsize = TYPE_SIZE_UNIT (argtype);
}
- /* MEMBER is either a bona fide flexible array member, or a zero-length
+ /* MEMBER is either a bona fide flexible array member, or a zero-elements
array member, or an array of length one treated as such. */
/* If the reference is to a declared object and the member a true