[PATCH] Fix PR58941
Richard Biener
rguenther@suse.de
Tue Nov 5 13:24:00 GMT 2013
The following fixes PR58941 - we fail to detect a trailing array
access in get_ref_base_and_extent because, while we remember
the type to check, we still apply an extra offset that confuses us.
Fixed by handling trailing arrays at places we view-convert.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk
sofar.
Richard.
2013-11-05 Richard Biener <rguenther@suse.de>
PR middle-end/58941
* tree-dfa.c (get_ref_base_and_extent): Merge common code
in MEM_REF and TARGET_MEM_REF handling. Make sure to
process trailing array detection before diving into the
view-converted object (and possibly apply some extra offset).
* gcc.dg/torture/pr58941.c: New testcase.
Index: gcc/tree-dfa.c
===================================================================
*** gcc/tree-dfa.c (revision 204346)
--- gcc/tree-dfa.c (working copy)
*************** get_ref_base_and_extent (tree exp, HOST_
*** 389,395 ****
double_int bit_offset = double_int_zero;
HOST_WIDE_INT hbit_offset;
bool seen_variable_array_ref = false;
- tree base_type;
/* First get the final access size from just the outermost expression. */
if (TREE_CODE (exp) == COMPONENT_REF)
--- 389,394 ----
*************** get_ref_base_and_extent (tree exp, HOST_
*** 420,427 ****
and find the ultimate containing object. */
while (1)
{
- base_type = TREE_TYPE (exp);
-
switch (TREE_CODE (exp))
{
case BIT_FIELD_REF:
--- 419,424 ----
*************** get_ref_base_and_extent (tree exp, HOST_
*** 544,550 ****
--- 541,578 ----
case VIEW_CONVERT_EXPR:
break;
+ case TARGET_MEM_REF:
+ /* Via the variable index or index2 we can reach the
+ whole object. Still hand back the decl here. */
+ if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR
+ && (TMR_INDEX (exp) || TMR_INDEX2 (exp)))
+ {
+ exp = TREE_OPERAND (TMR_BASE (exp), 0);
+ bit_offset = double_int_zero;
+ maxsize = -1;
+ goto done;
+ }
+ /* Fallthru. */
case MEM_REF:
+ /* We need to deal with variable arrays ending structures such as
+ struct { int length; int a[1]; } x; x.a[d]
+ struct { struct { int a; int b; } a[1]; } x; x.a[d].a
+ struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0]
+ struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
+ where we do not know maxsize for variable index accesses to
+ the array. The simplest way to conservatively deal with this
+ is to punt in the case that offset + maxsize reaches the
+ base type boundary. This needs to include possible trailing
+ padding that is there for alignment purposes. */
+ if (seen_variable_array_ref
+ && maxsize != -1
+ && (!bit_offset.fits_shwi ()
+ || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ || (bit_offset.to_shwi () + maxsize
+ == (signed) TREE_INT_CST_LOW
+ (TYPE_SIZE (TREE_TYPE (exp))))))
+ maxsize = -1;
+
/* Hand back the decl for MEM[&decl, off]. */
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
{
*************** get_ref_base_and_extent (tree exp, HOST_
*** 555,595 ****
double_int off = mem_ref_offset (exp);
off = off.lshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT));
- off = off + bit_offset;
- if (off.fits_shwi ())
- {
- bit_offset = off;
- exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- }
- }
- }
- goto done;
-
- case TARGET_MEM_REF:
- /* Hand back the decl for MEM[&decl, off]. */
- if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR)
- {
- /* Via the variable index or index2 we can reach the
- whole object. */
- if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
- {
- exp = TREE_OPERAND (TMR_BASE (exp), 0);
- bit_offset = double_int_zero;
- maxsize = -1;
- goto done;
- }
- if (integer_zerop (TMR_OFFSET (exp)))
- exp = TREE_OPERAND (TMR_BASE (exp), 0);
- else
- {
- double_int off = mem_ref_offset (exp);
- off = off.lshift (BITS_PER_UNIT == 8
- ? 3 : exact_log2 (BITS_PER_UNIT));
off += bit_offset;
if (off.fits_shwi ())
{
bit_offset = off;
! exp = TREE_OPERAND (TMR_BASE (exp), 0);
}
}
}
--- 583,593 ----
double_int off = mem_ref_offset (exp);
off = off.lshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT));
off += bit_offset;
if (off.fits_shwi ())
{
bit_offset = off;
! exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
}
}
}
*************** get_ref_base_and_extent (tree exp, HOST_
*** 601,608 ****
exp = TREE_OPERAND (exp, 0);
}
- done:
if (!bit_offset.fits_shwi ())
{
*poffset = 0;
--- 599,615 ----
exp = TREE_OPERAND (exp, 0);
}
+ /* We need to deal with variable arrays ending structures. */
+ if (seen_variable_array_ref
+ && maxsize != -1
+ && (!bit_offset.fits_shwi ()
+ || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ || (bit_offset.to_shwi () + maxsize
+ == (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
+ maxsize = -1;
+
+ done:
if (!bit_offset.fits_shwi ())
{
*poffset = 0;
*************** get_ref_base_and_extent (tree exp, HOST_
*** 614,637 ****
hbit_offset = bit_offset.to_shwi ();
- /* We need to deal with variable arrays ending structures such as
- struct { int length; int a[1]; } x; x.a[d]
- struct { struct { int a; int b; } a[1]; } x; x.a[d].a
- struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0]
- struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
- where we do not know maxsize for variable index accesses to
- the array. The simplest way to conservatively deal with this
- is to punt in the case that offset + maxsize reaches the
- base type boundary. This needs to include possible trailing padding
- that is there for alignment purposes. */
-
- if (seen_variable_array_ref
- && maxsize != -1
- && (!host_integerp (TYPE_SIZE (base_type), 1)
- || (hbit_offset + maxsize
- == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
- maxsize = -1;
-
/* In case of a decl or constant base object we can do better. */
if (DECL_P (exp))
--- 621,626 ----
Index: gcc/testsuite/gcc.dg/torture/pr58941.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr58941.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr58941.c (working copy)
***************
*** 0 ****
--- 1,33 ----
+ /* { dg-do run } */
+
+ extern void abort (void);
+
+ typedef struct {
+ int msgLength;
+ unsigned char data[1000];
+ } SMsg;
+
+ typedef struct {
+ int dummy;
+ int d[0];
+ } SData;
+
+ int condition = 3;
+
+ int main()
+ {
+ SMsg msg;
+ SData *pData = (SData*)(msg.data);
+ unsigned int i = 0;
+ for (i = 0; i < 1; i++)
+ {
+ pData->d[i] = 0;
+ if(condition & 1)
+ pData->d[i] |= 0x55;
+ if(condition & 2)
+ pData->d[i] |= 0xaa;
+ }
+ if (pData->d[0] != 0xff)
+ abort ();
+ return 0;
+ }
More information about the Gcc-patches
mailing list