re PR middle-end/57748 (ICE when expanding assignment to unaligned zero-sized array)

2013-09-20  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR middle-end/57748
        * expr.c (expand_assignment): Remove misalignp code path.

testsuite/

        PR middle-end/57748
        * gcc.dg/torture/pr57748-1.c: New test.
        * gcc.dg/torture/pr57748-2.c: New test.

From-SVN: r202778
This commit is contained in:
Bernd Edlinger 2013-09-20 14:10:14 +00:00 committed by Bernd Edlinger
parent a543001905
commit 59bb154488
5 changed files with 104 additions and 47 deletions

View File

@ -1,3 +1,8 @@
2013-09-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR middle-end/57748
* expr.c (expand_assignment): Remove misalignp code path.
2013-09-20 Marek Polacek <polacek@redhat.com>
PR sanitizer/58413

View File

@ -4709,8 +4709,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
int unsignedp;
int volatilep = 0;
tree tem;
bool misalignp;
rtx mem = NULL_RTX;
push_temp_slots ();
tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
@ -4720,40 +4718,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
&& DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
/* If we are going to use store_bit_field and extract_bit_field,
make sure to_rtx will be safe for multiple use. */
mode = TYPE_MODE (TREE_TYPE (tem));
if (TREE_CODE (tem) == MEM_REF
&& mode != BLKmode
&& ((align = get_object_alignment (tem))
< GET_MODE_ALIGNMENT (mode))
&& ((icode = optab_handler (movmisalign_optab, mode))
!= CODE_FOR_nothing))
{
struct expand_operand ops[2];
misalignp = true;
to_rtx = gen_reg_rtx (mode);
mem = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
/* If the misaligned store doesn't overwrite all bits, perform
rmw cycle on MEM. */
if (bitsize != GET_MODE_BITSIZE (mode))
{
create_input_operand (&ops[0], to_rtx, mode);
create_fixed_operand (&ops[1], mem);
/* The movmisalign<mode> pattern cannot fail, else the assignment
would silently be omitted. */
expand_insn (icode, 2, ops);
mem = copy_rtx (mem);
}
}
else
{
misalignp = false;
to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
}
to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
/* If the bitfield is volatile, we want to access it in the
field's mode, not the computed mode.
@ -4892,17 +4857,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
get_alias_set (to), nontemporal);
}
if (misalignp)
{
struct expand_operand ops[2];
create_fixed_operand (&ops[0], mem);
create_input_operand (&ops[1], to_rtx, mode);
/* The movmisalign<mode> pattern cannot fail, else the assignment
would silently be omitted. */
expand_insn (icode, 2, ops);
}
if (result)
preserve_temp_slots (result);
pop_temp_slots ();

View File

@ -1,3 +1,9 @@
2013-09-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR middle-end/57748
* gcc.dg/torture/pr57748-1.c: New test.
* gcc.dg/torture/pr57748-2.c: New test.
2013-09-20 Marek Polacek <polacek@redhat.com>
PR sanitizer/58413

View File

@ -0,0 +1,49 @@
/* PR middle-end/57748 */
/* { dg-do run } */
/* ICE in expand_assignment:
misalignp == true, !MEM_P (to_rtx), offset != 0,
=> gcc_assert (TREE_CODE (offset) == INTEGER_CST) */
#include <stdlib.h>
extern void abort (void);
typedef long long V
__attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
struct __attribute__((packed)) T { char c; P s; };
void __attribute__((noinline, noclone))
check (struct T *t)
{
if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4)
abort ();
}
int __attribute__((noinline, noclone))
get_i (void)
{
return 0;
}
void __attribute__((noinline, noclone))
foo (P *p)
{
V a = { 3, 4 };
int i = get_i ();
p->b[i] = a;
}
int
main ()
{
struct T *t = (struct T *) calloc (128, 1);
foo (&t->s);
check (t);
free (t);
return 0;
}

View File

@ -0,0 +1,43 @@
/* PR middle-end/57748 */
/* { dg-do run } */
/* wrong code in expand_assignment:
misalignp == true, !MEM_P (to_rtx),
offset == 0, bitpos >= GET_MODE_PRECISION,
=> result = NULL. */
#include <stdlib.h>
extern void abort (void);
typedef long long V
__attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
struct __attribute__((packed)) T { char c; P s; };
void __attribute__((noinline, noclone))
check (struct T *t)
{
if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4)
abort ();
}
void __attribute__((noinline, noclone))
foo (P *p)
{
V a = { 3, 4 };
p->b[0] = a;
}
int
main ()
{
struct T *t = (struct T *) calloc (128, 1);
foo (&t->s);
check (t);
free (t);
return 0;
}