aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-10-09 13:56:53 -0600
committerMartin Sebor <msebor@redhat.com>2020-10-12 09:04:49 -0600
commitde05c19d5fd661ae16dd75a895b49d32d12f5edc (patch)
tree05d9906c75f514094c4320b482f200787a34b9b6 /gcc/tree.c
parent71dbabccbfb295c87d91719fe72d9d60511c0b44 (diff)
downloadgcc-de05c19d5fd661ae16dd75a895b49d32d12f5edc.zip
gcc-de05c19d5fd661ae16dd75a895b49d32d12f5edc.tar.gz
gcc-de05c19d5fd661ae16dd75a895b49d32d12f5edc.tar.bz2
Correct handling of indices into arrays with elements larger than 1 (PR c++/96511)
Resolves: PR c++/96511 - Incorrect -Wplacement-new on POINTER_PLUS into an array with 4-byte elements PR middle-end/96384 - bogus -Wstringop-overflow= storing into multidimensional array with index in range gcc/ChangeLog: PR c++/96511 PR middle-end/96384 * builtins.c (get_range): Return full range of type when neither value nor its range is available. Fail for ranges inverted due to the signedness of offsets. (compute_objsize): Handle more special array members. Handle POINTER_PLUS_EXPR and VIEW_CONVERT_EXPR that come up in front end code. (access_ref::offset_bounded): Define new member function. * builtins.h (access_ref::eval): New data member. (access_ref::offset_bounded): New member function. (access_ref::offset_zero): New member function. (compute_objsize): Declare a new overload. * gimple-array-bounds.cc (array_bounds_checker::check_array_ref): Use enum special_array_member. * tree.c (component_ref_size): Use special_array_member. * tree.h (special_array_member): Define a new type. (component_ref_size): Change signature. gcc/cp/ChangeLog: PR c++/96511 PR middle-end/96384 * init.c (warn_placement_new_too_small): Call builtin_objsize instead of duplicating what it does. gcc/testsuite/ChangeLog: PR c++/96511 PR middle-end/96384 * g++.dg/init/strlen.C: Add expected warning. * g++.dg/warn/Wplacement-new-size-1.C: Relax warnings. * g++.dg/warn/Wplacement-new-size-2.C: Same. * g++.dg/warn/Wplacement-new-size-6.C: Same. * gcc.dg/Warray-bounds-58.c: Adjust * gcc.dg/Wstringop-overflow-37.c: Same. * g++.dg/warn/Wplacement-new-size-7.C: New test.
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c38
1 files changed, 25 insertions, 13 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index a1fc119..555ba97 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13640,20 +13640,21 @@ get_initializer_for (tree init, tree decl)
/* 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, *INTERIOR_ZERO_LENGTH is set when REF refers to
- an interior zero-length array.
+ If non-null, set *ARK when REF refers to an interior zero-length
+ array or a trailing one-element array.
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. */
tree
-component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
+component_ref_size (tree ref, special_array_member *sam /* = NULL */)
{
gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
- bool int_0_len = false;
- if (!interior_zero_length)
- interior_zero_length = &int_0_len;
+ special_array_member arkbuf;
+ if (!sam)
+ sam = &arkbuf;
+ *sam = special_array_member::none;
/* The object/argument referenced by the COMPONENT_REF and its type. */
tree arg = TREE_OPERAND (ref, 0);
@@ -13675,9 +13676,16 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
more than one element. */
return memsize;
- *interior_zero_length = zero_length && !trailing;
- if (*interior_zero_length)
- memsize = NULL_TREE;
+ if (zero_length)
+ {
+ if (trailing)
+ *sam = special_array_member::trail_0;
+ else
+ {
+ *sam = special_array_member::int_0;
+ memsize = NULL_TREE;
+ }
+ }
if (!zero_length)
if (tree dom = TYPE_DOMAIN (memtype))
@@ -13688,9 +13696,13 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
{
offset_int minidx = wi::to_offset (min);
offset_int maxidx = wi::to_offset (max);
- if (maxidx - minidx > 0)
+ 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;
}
/* For a refernce to a zero- or one-element array member of a union
@@ -13708,7 +13720,7 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
tree base = get_addr_base_and_unit_offset (ref, &baseoff);
if (!base || !VAR_P (base))
{
- if (!*interior_zero_length)
+ if (*sam != special_array_member::int_0)
return NULL_TREE;
if (TREE_CODE (arg) != COMPONENT_REF)
@@ -13728,7 +13740,7 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
/* Determine the base type of the referenced object. If it's
the same as ARGTYPE and MEMBER has a known size, return it. */
tree bt = basetype;
- if (!*interior_zero_length)
+ if (*sam != special_array_member::int_0)
while (TREE_CODE (bt) == ARRAY_TYPE)
bt = TREE_TYPE (bt);
bool typematch = useless_type_conversion_p (argtype, bt);
@@ -13768,7 +13780,7 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
if (DECL_P (base)
&& DECL_EXTERNAL (base)
&& bt == basetype
- && !*interior_zero_length)
+ && *sam != special_array_member::int_0)
/* The size of a flexible array member of an extern struct
with no initializer cannot be determined (it's defined
in another translation unit and can have an initializer