This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/69553] [6 Regression] Optimizations O1/O2 makes std::array value incorrect when passed to function
- From: "rguenth at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 16 Feb 2016 14:54:45 +0000
- Subject: [Bug middle-end/69553] [6 Regression] Optimizations O1/O2 makes std::array value incorrect when passed to function
- Auto-submitted: auto-generated
- References: <bug-69553-4 at http dot gcc dot gnu dot org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69553
--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> ---
So the issue is that
&MEM[(const struct B[2] &)p1_2(D)][1]
and
&MEM[(const int[2] &)p1_2(D)][1]
are considered equal even though we have int[] vs. B[] and thus different
element sizes and different offsets (but same array indices) here.
For COMPONENT_REFs we compare the FIELD_DECL but for ARRAY_REFs and also
for IMAGPART_EXPR we fail to consider the element size.
Not that comparing TYPE_PRECISION on MEM_REFs of ARRAY_TYPE makes any sense,
or TYPE_UNSIGNED.
So the old code had bugs as well here (consider array types with different
low bound).
Index: fold-const.c
===================================================================
--- fold-const.c (revision 233447)
+++ fold-const.c (working copy)
@@ -3008,8 +3008,15 @@ operand_equal_p (const_tree arg0, const_
flags &= ~OEP_ADDRESS_OF;
return OP_SAME (0);
- case REALPART_EXPR:
case IMAGPART_EXPR:
+ /* Require the same offset. */
+ if (!operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
+ TYPE_SIZE (TREE_TYPE (arg1)),
+ flags & ~OEP_ADDRESS_OF)))
+ return 0;
+
+ /* Fallthru. */
+ case REALPART_EXPR:
case VIEW_CONVERT_EXPR:
return OP_SAME (0);
@@ -3049,17 +3056,24 @@ operand_equal_p (const_tree arg0, const_
case ARRAY_REF:
case ARRAY_RANGE_REF:
- /* Operands 2 and 3 may be null.
- Compare the array index by value if it is constant first as we
- may have different types but same value here. */
if (!OP_SAME (0))
return 0;
flags &= ~OEP_ADDRESS_OF;
+ /* Compare the array index by value if it is constant first as we
+ may have different types but same value here.
+ Compare low bound and element size as with OEP_ADDRESS_OF
+ we have to account for the offset of the ref. */
return ((tree_int_cst_equal (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1))
|| OP_SAME (1))
- && OP_SAME_WITH_NULL (2)
- && OP_SAME_WITH_NULL (3));
+ && operand_equal_p (array_ref_low_bound
+ (CONST_CAST_TREE (arg0)),
+ array_ref_low_bound
+ (CONST_CAST_TREE (arg1)), flags)
+ && operand_equal_p (array_ref_element_size
+ (CONST_CAST_TREE (arg0)),
+ array_ref_element_size
+ (CONST_CAST_TREE (arg1)), flags));
case COMPONENT_REF:
/* Handle operand 2 the same as for ARRAY_REF. Operand 0