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 <rguent...@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; + }