aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 1aabffe..54e471a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13600,6 +13600,10 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
if (!interior_zero_length)
interior_zero_length = &int_0_len;
+ /* The object/argument referenced by the COMPONENT_REF and its type. */
+ tree arg = TREE_OPERAND (ref, 0);
+ tree argtype = TREE_TYPE (arg);
+ /* The referenced member. */
tree member = TREE_OPERAND (ref, 1);
tree memsize = DECL_SIZE_UNIT (member);
@@ -13611,7 +13615,7 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
bool trailing = array_at_struct_end_p (ref);
bool zero_length = integer_zerop (memsize);
- if (!trailing && (!interior_zero_length || !zero_length))
+ if (!trailing && !zero_length)
/* MEMBER is either an interior array or is an array with
more than one element. */
return memsize;
@@ -13630,9 +13634,14 @@ 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)
- /* MEMBER is an array with more than 1 element. */
+ /* MEMBER is an array with more than one element. */
return memsize;
}
+
+ /* For a refernce to a zero- or one-element 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);
}
/* MEMBER is either a bona fide flexible array member, or a zero-length
@@ -13647,28 +13656,27 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
if (!*interior_zero_length)
return NULL_TREE;
- if (TREE_CODE (TREE_OPERAND (ref, 0)) != COMPONENT_REF)
+ if (TREE_CODE (arg) != COMPONENT_REF)
return NULL_TREE;
- base = TREE_OPERAND (ref, 0);
+ base = arg;
while (TREE_CODE (base) == COMPONENT_REF)
base = TREE_OPERAND (base, 0);
baseoff = tree_to_poly_int64 (byte_position (TREE_OPERAND (ref, 1)));
}
/* BASE is the declared object of which MEMBER is either a member
- or that is cast to REFTYPE (e.g., a char buffer used to store
- a REFTYPE object). */
- tree reftype = TREE_TYPE (TREE_OPERAND (ref, 0));
+ or that is cast to ARGTYPE (e.g., a char buffer used to store
+ an ARGTYPE object). */
tree basetype = TREE_TYPE (base);
/* Determine the base type of the referenced object. If it's
- the same as REFTYPE and MEMBER has a known size, return it. */
+ the same as ARGTYPE and MEMBER has a known size, return it. */
tree bt = basetype;
if (!*interior_zero_length)
while (TREE_CODE (bt) == ARRAY_TYPE)
bt = TREE_TYPE (bt);
- bool typematch = useless_type_conversion_p (reftype, bt);
+ bool typematch = useless_type_conversion_p (argtype, bt);
if (memsize && typematch)
return memsize;
@@ -13684,7 +13692,7 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
if (init)
{
memsize = TYPE_SIZE_UNIT (TREE_TYPE (init));
- if (tree refsize = TYPE_SIZE_UNIT (reftype))
+ if (tree refsize = TYPE_SIZE_UNIT (argtype))
{
/* Use the larger of the initializer size and the tail
padding in the enclosing struct. */