diff options
author | Martin Sebor <msebor@redhat.com> | 2020-10-09 13:56:53 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-10-12 09:04:49 -0600 |
commit | de05c19d5fd661ae16dd75a895b49d32d12f5edc (patch) | |
tree | 05d9906c75f514094c4320b482f200787a34b9b6 /gcc/tree.c | |
parent | 71dbabccbfb295c87d91719fe72d9d60511c0b44 (diff) | |
download | gcc-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.c | 38 |
1 files changed, 25 insertions, 13 deletions
@@ -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 |