public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, PR 57748] Check for out of bounds access
@ 2013-09-06  7:03 Bernd Edlinger
  2013-09-06  7:31 ` Richard Biener
  2013-09-06  9:29 ` [PATCH, PR 57748] Check for out of bounds access Eric Botcazou
  0 siblings, 2 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-06  7:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Biener

[-- Attachment #1: Type: text/plain, Size: 361 bytes --]

Hi,

this patch fixes the ICE and wrong code issues from PR57748. It contains two test cases.
One for the ICE and one for the wrong code. Both test cases fail for all gcc versions,
and are fixed with this patch.

Bootstrapped and tested on x86_64-linux without any problems.

OK for trunk and the 4.8 / 4.7 branch?

Regards
Bernd Edlinger 		 	   		  

[-- Attachment #2: changelog-pr57748.txt --]
[-- Type: text/plain, Size: 252 bytes --]

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

	PR middle-end/57748
	* expr.c (expand_assignment): Check for out of bounds
	access to structures.

testsuite:

	* gcc.dg/torture/pr57748-1.c: New test.
	* gcc.dg/torture/pr57748-2.c: New test.


[-- Attachment #3: patch-pr57748.diff --]
[-- Type: application/octet-stream, Size: 2938 bytes --]

--- gcc/expr.c	2013-08-06 00:09:45.000000000 +0200
+++ gcc/expr.c	2013-09-03 00:46:28.000000000 +0200
@@ -4707,6 +4707,9 @@ expand_assignment (tree to, tree from, b
       mode = TYPE_MODE (TREE_TYPE (tem));
       if (TREE_CODE (tem) == MEM_REF
 	  && mode != BLKmode
+	  && offset == 0
+	  && bitpos + bitsize <= GET_MODE_BITSIZE (mode)
+	  && !volatilep
 	  && ((align = get_object_alignment (tem))
 	      < GET_MODE_ALIGNMENT (mode))
 	  && ((icode = optab_handler (movmisalign_optab, mode))
@@ -4773,6 +4776,8 @@ expand_assignment (tree to, tree from, b
 	  if (MEM_P (to_rtx)
 	      && GET_MODE (to_rtx) == BLKmode
 	      && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
+	      && bitregion_start == 0
+	      && bitregion_end == 0
 	      && bitsize > 0
 	      && (bitpos % bitsize) == 0
 	      && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
--- gcc/testsuite/gcc.dg/torture/pr57748-1.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-1.c	2013-09-06 08:38:03.718686940 +0200
@@ -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;
+}
--- gcc/testsuite/gcc.dg/torture/pr57748-2.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-2.c	2013-09-06 08:38:03.718686940 +0200
@@ -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;
+}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-06  7:03 [PATCH, PR 57748] Check for out of bounds access Bernd Edlinger
@ 2013-09-06  7:31 ` Richard Biener
       [not found]   ` <DUB122-W323D4AAAEA1AFA890BF243E43C0@phx.gbl>
  2013-09-06  9:29 ` [PATCH, PR 57748] Check for out of bounds access Eric Botcazou
  1 sibling, 1 reply; 105+ messages in thread
From: Richard Biener @ 2013-09-06  7:31 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches

On Fri, Sep 6, 2013 at 9:03 AM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi,
>
> this patch fixes the ICE and wrong code issues from PR57748. It contains two test cases.
> One for the ICE and one for the wrong code. Both test cases fail for all gcc versions,
> and are fixed with this patch.
>
> Bootstrapped and tested on x86_64-linux without any problems.
>
> OK for trunk and the 4.8 / 4.7 branch?

This doesn't look like the correct test.  The movmisalign optab query
uses the wrong mode.

Richard.

> Regards
> Bernd Edlinger

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
       [not found]       ` <DUB122-W4D571A91831593BA22438E43C0@phx.gbl>
@ 2013-09-06  9:19         ` Richard Biener
  2013-09-06  9:30           ` Bernd Edlinger
  2013-09-10 21:33           ` Martin Jambor
  0 siblings, 2 replies; 105+ messages in thread
From: Richard Biener @ 2013-09-06  9:19 UTC (permalink / raw)
  To: Bernd Edlinger, Martin Jambor, GCC Patches

On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Richard,
>
>> But the movmisalign path skips all this code and with the
>> current code thinks the actual access is in the mode of the
>> whole structure. (and also misses the address adjustment
>> as shown in the other testcase for the bug)
>>
>> The movmisalign handling in this path is just broken. And
>> it's _not_ just for optimization! If you have
>>
>> struct __attribute__((packed)) {
>> double x;
>> v2df y;
>> } *p;
>>
>> and do
>>
>> p = malloc (48); // gets you 8-byte aligned memory
>> p->y = (v2df) { 1., 2. };
>>
>> then you cannot skip the movmisaling handling because
>> we'd generate an aligned move (based on the mode) then.
>>
>
> Ok, test examples are really helpful here.
>
> This time the structure is BLKmode, unaligned,
> movmisalign = false anyway.
>
> I tried to make a test case out of your example,
> and as I expected, the code is also correct:
>
> foo:
>         .cfi_startproc
>         movdqa  .LC1(%rip), %xmm0
>         movq    $-1, (%rdi)
>         movl    $0x4048f5c3, 8(%rdi)
>         movdqu  %xmm0, 12(%rdi)
>         ret
>
> movdqu.
>
> The test executes without trap.
> And I did everything to make the object unaligned.

Yeah, well - for the expand path with BLKmode it's working fine.
We're doing all
the dances because of correctness for non-BLKmode expand paths.

> I am sure we could completely remove the
> movmisalign path, and nothing would happen.
> probably. except maybe for a performance regression.

In this place probably yes.  But we can also fix it to use the proper mode and
properly do the offset adjustment.  But just adding a bounds check looks
broken to me.

Note that there may have been a correctness reason for this code in the
light of the IPA-SRA code.  Maybe Martin remembers.

If removing the movmisalign handling inside the handled-component
case in expand_assignment works out (make sure to also test a
strict-alignment target) then that is probably fine.

Richard.

>
> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-06  7:03 [PATCH, PR 57748] Check for out of bounds access Bernd Edlinger
  2013-09-06  7:31 ` Richard Biener
@ 2013-09-06  9:29 ` Eric Botcazou
  2013-09-06  9:30   ` Jakub Jelinek
  1 sibling, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-09-06  9:29 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener

> this patch fixes the ICE and wrong code issues from PR57748. It contains two
> test cases. One for the ICE and one for the wrong code. Both test cases
> fail for all gcc versions, and are fixed with this patch.
> 
> Bootstrapped and tested on x86_64-linux without any problems.
> 
> OK for trunk and the 4.8 / 4.7 branch?

Please avoid touching the 4.7 branch at this point, this is a sensitive area 
and the testcases look quite artificial to me.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-06  9:29 ` [PATCH, PR 57748] Check for out of bounds access Eric Botcazou
@ 2013-09-06  9:30   ` Jakub Jelinek
  2013-09-06 10:30     ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Jakub Jelinek @ 2013-09-06  9:30 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: Bernd Edlinger, gcc-patches, Richard Biener

On Fri, Sep 06, 2013 at 11:28:44AM +0200, Eric Botcazou wrote:
> > this patch fixes the ICE and wrong code issues from PR57748. It contains two
> > test cases. One for the ICE and one for the wrong code. Both test cases
> > fail for all gcc versions, and are fixed with this patch.
> > 
> > Bootstrapped and tested on x86_64-linux without any problems.
> > 
> > OK for trunk and the 4.8 / 4.7 branch?
> 
> Please avoid touching the 4.7 branch at this point, this is a sensitive area 
> and the testcases look quite artificial to me.

Even for 4.8 it needs at least several weeks on the trunk before considering
backports of such code.

	Jakub

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-06  9:19         ` Richard Biener
@ 2013-09-06  9:30           ` Bernd Edlinger
  2013-09-10 21:33           ` Martin Jambor
  1 sibling, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-06  9:30 UTC (permalink / raw)
  To: Richard Biener, Martin Jambor, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 2280 bytes --]

Just for completeness, these were the test examples on
this private communication:

On Fri, 6 Sep 2013 11:19:18, Richard Biener wrote:
> On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
>> Richard,
>>
>>> But the movmisalign path skips all this code and with the
>>> current code thinks the actual access is in the mode of the
>>> whole structure. (and also misses the address adjustment
>>> as shown in the other testcase for the bug)
>>>
>>> The movmisalign handling in this path is just broken. And
>>> it's _not_ just for optimization! If you have
>>>
>>> struct __attribute__((packed)) {
>>> double x;
>>> v2df y;
>>> } *p;
>>>
>>> and do
>>>
>>> p = malloc (48); // gets you 8-byte aligned memory
>>> p->y = (v2df) { 1., 2. };
>>>
>>> then you cannot skip the movmisaling handling because
>>> we'd generate an aligned move (based on the mode) then.
>>>
>>
>> Ok, test examples are really helpful here.
>>
>> This time the structure is BLKmode, unaligned,
>> movmisalign = false anyway.
>>
>> I tried to make a test case out of your example,
>> and as I expected, the code is also correct:
>>
>> foo:
>> .cfi_startproc
>> movdqa .LC1(%rip), %xmm0
>> movq $-1, (%rdi)
>> movl $0x4048f5c3, 8(%rdi)
>> movdqu %xmm0, 12(%rdi)
>> ret
>>
>> movdqu.
>>
>> The test executes without trap.
>> And I did everything to make the object unaligned.
>
> Yeah, well - for the expand path with BLKmode it's working fine.
> We're doing all
> the dances because of correctness for non-BLKmode expand paths.
>
>> I am sure we could completely remove the
>> movmisalign path, and nothing would happen.
>> probably. except maybe for a performance regression.
>
> In this place probably yes. But we can also fix it to use the proper mode and
> properly do the offset adjustment. But just adding a bounds check looks
> broken to me.
>
> Note that there may have been a correctness reason for this code in the
> light of the IPA-SRA code. Maybe Martin remembers.
>
> If removing the movmisalign handling inside the handled-component
> case in expand_assignment works out (make sure to also test a
> strict-alignment target) then that is probably fine.
>
> Richard.
>
>>
>> Bernd. 		 	   		  

[-- Attachment #2: x.c --]
[-- Type: text/plain, Size: 563 bytes --]

#include <stdio.h>
#include <string.h>

typedef long long V
  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
union x
{
   long long a;
   float b;
} __attribute__((aligned(1))) ;

struct s
{
  union x xx[0];
  V x;
  
} __attribute__((packed));

void __attribute__((noinline, noclone))
foo(struct s * x)
{
  x->xx[0].a = -1;
  x->xx[0].b = 3.14;
  x->x[1] = 0x123456789ABCDEF;
}

int
main()
{
  struct s ss;
  memset(&ss, 0, sizeof(ss));
  foo (&ss);
  printf("%f %llX\n", ss.xx[0].b, ss.xx[0].a);
  printf("%llX %llX\n", ss.x[0], ss.x[1]);
}

[-- Attachment #3: y.c --]
[-- Type: text/plain, Size: 532 bytes --]

#include <stdio.h>
#include <string.h>

typedef long long V
  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));

struct __attribute__((packed)) s
{
   long long a;
   float b;
   V x;
};

void __attribute__((noinline, noclone))
foo(struct s * x)
{
  V a = { 1, 2 };
  x->a = -1;
  x->b = 3.14;
  x->x = a;
}

int
main()
{
  long long buf[100];
  struct s* ss = (struct s*) ((char*)buf+1);
  memset(ss, 0, sizeof(*ss));
  foo (ss);
  printf("%f %llX\n", ss->b, ss->a);
  printf("%llX %llX\n", ss->x[0], ss->x[1]);
}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-06  9:30   ` Jakub Jelinek
@ 2013-09-06 10:30     ` Bernd Edlinger
  0 siblings, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-06 10:30 UTC (permalink / raw)
  To: Jakub Jelinek, Eric Botcazou; +Cc: gcc-patches, Richard Biener

On Fri, 6 Sep 2013 11:30:53, Jakub Jelinek wrote:
> On Fri, Sep 06, 2013 at 11:28:44AM +0200, Eric Botcazou wrote:
>>> this patch fixes the ICE and wrong code issues from PR57748. It contains two
>>> test cases. One for the ICE and one for the wrong code. Both test cases
>>> fail for all gcc versions, and are fixed with this patch.
>>>
>>> Bootstrapped and tested on x86_64-linux without any problems.
>>>
>>> OK for trunk and the 4.8 / 4.7 branch?
>>
>> Please avoid touching the 4.7 branch at this point, this is a sensitive area
>> and the testcases look quite artificial to me.
>
> Even for 4.8 it needs at least several weeks on the trunk before considering
> backports of such code.
>
> Jakub

That's true, the examples are quite artificial, because it is difficult
and quite target-dependent, if there will be a movmisalign optab at all.

And the original test case will no longer reproduce on trunk because of this
change:

2013-08-08  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
    PR target/58065
    * config/arm/arm.h (MALLOC_ABI_ALIGNMENT): Define.
 
maybe we should first backport this one.

Yesterday someone did that on the linaro branch,
but maybe /branches/gcc-4_8-branch should be updated as well?

Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-06  9:19         ` Richard Biener
  2013-09-06  9:30           ` Bernd Edlinger
@ 2013-09-10 21:33           ` Martin Jambor
  2013-09-11 14:42             ` Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Martin Jambor @ 2013-09-10 21:33 UTC (permalink / raw)
  To: Richard Biener; +Cc: Bernd Edlinger, GCC Patches

Hi,

On Fri, Sep 06, 2013 at 11:19:18AM +0200, Richard Biener wrote:
> On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
> > Richard,
> >
> >> But the movmisalign path skips all this code and with the
> >> current code thinks the actual access is in the mode of the
> >> whole structure. (and also misses the address adjustment
> >> as shown in the other testcase for the bug)
> >>
> >> The movmisalign handling in this path is just broken. And
> >> it's _not_ just for optimization! If you have
> >>
> >> struct __attribute__((packed)) {
> >> double x;
> >> v2df y;
> >> } *p;
> >>
> >> and do
> >>
> >> p = malloc (48); // gets you 8-byte aligned memory
> >> p->y = (v2df) { 1., 2. };
> >>
> >> then you cannot skip the movmisaling handling because
> >> we'd generate an aligned move (based on the mode) then.
> >>
> >
> > Ok, test examples are really helpful here.
> >
> > This time the structure is BLKmode, unaligned,
> > movmisalign = false anyway.
> >
> > I tried to make a test case out of your example,
> > and as I expected, the code is also correct:
> >
> > foo:
> >         .cfi_startproc
> >         movdqa  .LC1(%rip), %xmm0
> >         movq    $-1, (%rdi)
> >         movl    $0x4048f5c3, 8(%rdi)
> >         movdqu  %xmm0, 12(%rdi)
> >         ret
> >
> > movdqu.
> >
> > The test executes without trap.
> > And I did everything to make the object unaligned.
> 
> Yeah, well - for the expand path with BLKmode it's working fine.
> We're doing all
> the dances because of correctness for non-BLKmode expand paths.
> 
> > I am sure we could completely remove the
> > movmisalign path, and nothing would happen.
> > probably. except maybe for a performance regression.
> 
> In this place probably yes.  But we can also fix it to use the proper mode and
> properly do the offset adjustment.  But just adding a bounds check looks
> broken to me.
> 
> Note that there may have been a correctness reason for this code in the
> light of the IPA-SRA code.  Maybe Martin remembers.
> 

The misalignp path was added by you during the 4.7 development to fix
PR 50444 which was indeed about expansion of a SRA generated statement

MEM[(struct Engine *)e_1(D) + 40B].m = SR.18_17;

If I disable this path on the 4.7 branch, the testcase is compiled
incorrectly and aborts when run, apparently at least the 4.7's
combination of expand_normal and store_field cannot cope with it.

The path no longer tests the testcase though, because the component
ref is not present in trunk, the LHS is now just

MEM[(struct Engine *)e_3(D) + 40B]

and so it is now handled just fine by the misaligned mem-ref case at
the beginning of expand_assignment.

> If removing the movmisalign handling inside the handled-component
> case in expand_assignment works out (make sure to also test a
> strict-alignment target) then that is probably fine.
> 

I think we'd also better check that we do have a test where we expand
a COMPONENT_REF encapsulating a misaligned MEM_REF and a misaligned
MEM_REF that is mem_ref_refers_to_non_mem_p.

I'm now going through all the new comments in bugzilla and the
testcases to see if I can still be of any help.

Martin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-10 21:33           ` Martin Jambor
@ 2013-09-11 14:42             ` Bernd Edlinger
  2013-09-11 14:47               ` Richard Biener
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-11 14:42 UTC (permalink / raw)
  To: Martin Jambor, Richard Biener; +Cc: GCC Patches

On Tue, 10 Sep 2013 21:32:29, Martin Jambor wrote:
> Hi,
>
> On Fri, Sep 06, 2013 at 11:19:18AM +0200, Richard Biener wrote:
>> On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger
>> <bernd.edlinger@hotmail.de> wrote:
>>> Richard,
>>>
>>>> But the movmisalign path skips all this code and with the
>>>> current code thinks the actual access is in the mode of the
>>>> whole structure. (and also misses the address adjustment
>>>> as shown in the other testcase for the bug)
>>>>
>>>> The movmisalign handling in this path is just broken. And
>>>> it's _not_ just for optimization! If you have
>>>>
>>>> struct __attribute__((packed)) {
>>>> double x;
>>>> v2df y;
>>>> } *p;
>>>>
>>>> and do
>>>>
>>>> p = malloc (48); // gets you 8-byte aligned memory
>>>> p->y = (v2df) { 1., 2. };
>>>>
>>>> then you cannot skip the movmisaling handling because
>>>> we'd generate an aligned move (based on the mode) then.
>>>>
>>>
>>> Ok, test examples are really helpful here.
>>>
>>> This time the structure is BLKmode, unaligned,
>>> movmisalign = false anyway.
>>>
>>> I tried to make a test case out of your example,
>>> and as I expected, the code is also correct:
>>>
>>> foo:
>>> .cfi_startproc
>>> movdqa .LC1(%rip), %xmm0
>>> movq $-1, (%rdi)
>>> movl $0x4048f5c3, 8(%rdi)
>>> movdqu %xmm0, 12(%rdi)
>>> ret
>>>
>>> movdqu.
>>>
>>> The test executes without trap.
>>> And I did everything to make the object unaligned.
>>
>> Yeah, well - for the expand path with BLKmode it's working fine.
>> We're doing all
>> the dances because of correctness for non-BLKmode expand paths.
>>
>>> I am sure we could completely remove the
>>> movmisalign path, and nothing would happen.
>>> probably. except maybe for a performance regression.
>>
>> In this place probably yes. But we can also fix it to use the proper mode and
>> properly do the offset adjustment. But just adding a bounds check looks
>> broken to me.
>>
>> Note that there may have been a correctness reason for this code in the
>> light of the IPA-SRA code. Maybe Martin remembers.
>>
>
> The misalignp path was added by you during the 4.7 development to fix
> PR 50444 which was indeed about expansion of a SRA generated statement
>
> MEM[(struct Engine *)e_1(D) + 40B].m = SR.18_17;
>
> If I disable this path on the 4.7 branch, the testcase is compiled
> incorrectly and aborts when run, apparently at least the 4.7's
> combination of expand_normal and store_field cannot cope with it.
>
> The path no longer tests the testcase though, because the component
> ref is not present in trunk, the LHS is now just
>
> MEM[(struct Engine *)e_3(D) + 40B]
>
> and so it is now handled just fine by the misaligned mem-ref case at
> the beginning of expand_assignment.

I tried to remove the misaligned mem-ref case at the beginning of the
expand_assignment, just to see how it fails. I did this on trunk.

But still all testcases pass,  including pr50444.c...

How can this be?

>> If removing the movmisalign handling inside the handled-component
>> case in expand_assignment works out (make sure to also test a
>> strict-alignment target) then that is probably fine.
>>
>
> I think we'd also better check that we do have a test where we expand
> a COMPONENT_REF encapsulating a misaligned MEM_REF and a misaligned
> MEM_REF that is mem_ref_refers_to_non_mem_p.
>
> I'm now going through all the new comments in bugzilla and the
> testcases to see if I can still be of any help.
>
> Martin 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-11 14:42             ` Bernd Edlinger
@ 2013-09-11 14:47               ` Richard Biener
  2013-09-12 21:07                 ` Bernd Edlinger
  2013-09-15 19:08                 ` Bernd Edlinger
  0 siblings, 2 replies; 105+ messages in thread
From: Richard Biener @ 2013-09-11 14:47 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches

On Wed, Sep 11, 2013 at 3:41 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> On Tue, 10 Sep 2013 21:32:29, Martin Jambor wrote:
>> Hi,
>>
>> On Fri, Sep 06, 2013 at 11:19:18AM +0200, Richard Biener wrote:
>>> On Fri, Sep 6, 2013 at 10:35 AM, Bernd Edlinger
>>> <bernd.edlinger@hotmail.de> wrote:
>>>> Richard,
>>>>
>>>>> But the movmisalign path skips all this code and with the
>>>>> current code thinks the actual access is in the mode of the
>>>>> whole structure. (and also misses the address adjustment
>>>>> as shown in the other testcase for the bug)
>>>>>
>>>>> The movmisalign handling in this path is just broken. And
>>>>> it's _not_ just for optimization! If you have
>>>>>
>>>>> struct __attribute__((packed)) {
>>>>> double x;
>>>>> v2df y;
>>>>> } *p;
>>>>>
>>>>> and do
>>>>>
>>>>> p = malloc (48); // gets you 8-byte aligned memory
>>>>> p->y = (v2df) { 1., 2. };
>>>>>
>>>>> then you cannot skip the movmisaling handling because
>>>>> we'd generate an aligned move (based on the mode) then.
>>>>>
>>>>
>>>> Ok, test examples are really helpful here.
>>>>
>>>> This time the structure is BLKmode, unaligned,
>>>> movmisalign = false anyway.
>>>>
>>>> I tried to make a test case out of your example,
>>>> and as I expected, the code is also correct:
>>>>
>>>> foo:
>>>> .cfi_startproc
>>>> movdqa .LC1(%rip), %xmm0
>>>> movq $-1, (%rdi)
>>>> movl $0x4048f5c3, 8(%rdi)
>>>> movdqu %xmm0, 12(%rdi)
>>>> ret
>>>>
>>>> movdqu.
>>>>
>>>> The test executes without trap.
>>>> And I did everything to make the object unaligned.
>>>
>>> Yeah, well - for the expand path with BLKmode it's working fine.
>>> We're doing all
>>> the dances because of correctness for non-BLKmode expand paths.
>>>
>>>> I am sure we could completely remove the
>>>> movmisalign path, and nothing would happen.
>>>> probably. except maybe for a performance regression.
>>>
>>> In this place probably yes. But we can also fix it to use the proper mode and
>>> properly do the offset adjustment. But just adding a bounds check looks
>>> broken to me.
>>>
>>> Note that there may have been a correctness reason for this code in the
>>> light of the IPA-SRA code. Maybe Martin remembers.
>>>
>>
>> The misalignp path was added by you during the 4.7 development to fix
>> PR 50444 which was indeed about expansion of a SRA generated statement
>>
>> MEM[(struct Engine *)e_1(D) + 40B].m = SR.18_17;
>>
>> If I disable this path on the 4.7 branch, the testcase is compiled
>> incorrectly and aborts when run, apparently at least the 4.7's
>> combination of expand_normal and store_field cannot cope with it.
>>
>> The path no longer tests the testcase though, because the component
>> ref is not present in trunk, the LHS is now just
>>
>> MEM[(struct Engine *)e_3(D) + 40B]
>>
>> and so it is now handled just fine by the misaligned mem-ref case at
>> the beginning of expand_assignment.
>
> I tried to remove the misaligned mem-ref case at the beginning of the
> expand_assignment, just to see how it fails. I did this on trunk.
>
> But still all testcases pass,  including pr50444.c...
>
> How can this be?

Not sure.  Can you try reverting the fix itself and bisect when the testcase
will start to pass?  (maybe the testcase passed even without the fix?)

Richard.

>>> If removing the movmisalign handling inside the handled-component
>>> case in expand_assignment works out (make sure to also test a
>>> strict-alignment target) then that is probably fine.
>>>
>>
>> I think we'd also better check that we do have a test where we expand
>> a COMPONENT_REF encapsulating a misaligned MEM_REF and a misaligned
>> MEM_REF that is mem_ref_refers_to_non_mem_p.
>>
>> I'm now going through all the new comments in bugzilla and the
>> testcases to see if I can still be of any help.
>>
>> Martin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-11 14:47               ` Richard Biener
@ 2013-09-12 21:07                 ` Bernd Edlinger
  2013-09-13  9:37                   ` Eric Botcazou
  2013-09-15 19:08                 ` Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-12 21:07 UTC (permalink / raw)
  To: Richard Biener; +Cc: Martin Jambor, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 2456 bytes --]

On Wed, 11 Sep 2013 15:43:53, Richard Biener wrote:
> On Wed, Sep 11, 2013 at 3:41 PM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
>> On Tue, 10 Sep 2013 21:32:29, Martin Jambor wrote:
>>> The misalignp path was added by you during the 4.7 development to fix
>>> PR 50444 which was indeed about expansion of a SRA generated statement
>>>
>>> MEM[(struct Engine *)e_1(D) + 40B].m = SR.18_17;
>>>
>>> If I disable this path on the 4.7 branch, the testcase is compiled
>>> incorrectly and aborts when run, apparently at least the 4.7's
>>> combination of expand_normal and store_field cannot cope with it.
>>>
>>> The path no longer tests the testcase though, because the component
>>> ref is not present in trunk, the LHS is now just
>>>
>>> MEM[(struct Engine *)e_3(D) + 40B]
>>>
>>> and so it is now handled just fine by the misaligned mem-ref case at
>>> the beginning of expand_assignment.
>>
>> I tried to remove the misaligned mem-ref case at the beginning of the
>> expand_assignment, just to see how it fails. I did this on trunk.
>>
>> But still all testcases pass, including pr50444.c...
>>
>> How can this be?
>
> Not sure. Can you try reverting the fix itself and bisect when the testcase
> will start to pass? (maybe the testcase passed even without the fix?)
>
> Richard.

What I found out is this:

If the movmisalign_optab is replaced by mov_optab it does still generate
correct code. In 4.9, 4.8 and 4.7 too. The reason is that the back-end accesses
MEM_ALIGN(to_rtx) in mov_optab and movmisalign_optab to decide if
movdqa or movdqu is needed.

While it is straight forward to remove the movmisalign path in 4.9 and 4.8,
this is not so simple in the 4.7 branch. The reason is that 4.7 uses 
"to_rtx = expand_normal (tem);" while 4.8 and 4.9 use
"to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);"
which does almost the same, but returns the misaligned rtx instead of
an register with the value of the structure. And the generated code without
the misalign path fails simply because the assignment goes to the register
instead of the structure.

So the problem is: there is no EXPAND_WRITE/EXPAND_MEMORY in 4.7...

A possible patch for 4.7 would be like the attached (untested) patch.

With this pr50444.c, and pr57748-1..3.c would pass, but not pr57748-4.c
as the read side would still be wrong, but back-porting this would be even
more ugly :(

Bernd. 		 	   		  

[-- Attachment #2: patch-pr57748-4_7.diff --]
[-- Type: application/octet-stream, Size: 2305 bytes --]

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(Revision 202295)
+++ gcc/expr.c	(Arbeitskopie)
@@ -4641,8 +4641,6 @@
       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,
@@ -4664,14 +4662,10 @@
 	{
 	  enum machine_mode address_mode;
 	  rtx op0;
-	  struct expand_operand ops[2];
 	  addr_space_t as = TYPE_ADDR_SPACE
 	      (TREE_TYPE (TREE_TYPE (TREE_OPERAND (tem, 0))));
 	  tree base = TREE_OPERAND (tem, 0);
 
-	  misalignp = true;
-	  to_rtx = gen_reg_rtx (mode);
-
 	  address_mode = targetm.addr_space.address_mode (as);
 	  op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL);
 	  op0 = convert_memory_address_addr_space (address_mode, op0, as);
@@ -4682,28 +4676,14 @@
 	      op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
 	    }
 	  op0 = memory_address_addr_space (mode, op0, as);
-	  mem = gen_rtx_MEM (mode, op0);
-	  set_mem_attributes (mem, tem, 0);
-	  set_mem_addr_space (mem, as);
+	  to_rtx = gen_rtx_MEM (mode, op0);
+	  set_mem_attributes (to_rtx, tem, 0);
+	  set_mem_addr_space (to_rtx, as);
 	  if (TREE_THIS_VOLATILE (tem))
-	    MEM_VOLATILE_P (mem) = 1;
-
-	  /* 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);
-	    }
+	    MEM_VOLATILE_P (to_rtx) = 1;
 	}
       else
 	{
-	  misalignp = false;
 	  to_rtx = expand_normal (tem);
 	}
 
@@ -4851,17 +4831,6 @@
 				  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);
       free_temp_slots ();

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-12 21:07                 ` Bernd Edlinger
@ 2013-09-13  9:37                   ` Eric Botcazou
  2013-09-13  9:48                     ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-09-13  9:37 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor

> While it is straight forward to remove the movmisalign path in 4.9 and 4.8,
> this is not so simple in the 4.7 branch. The reason is that 4.7 uses
> "to_rtx = expand_normal (tem);" while 4.8 and 4.9 use
> "to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);"
> which does almost the same, but returns the misaligned rtx instead of
> an register with the value of the structure. And the generated code without
> the misalign path fails simply because the assignment goes to the register
> instead of the structure.
> 
> So the problem is: there is no EXPAND_WRITE/EXPAND_MEMORY in 4.7...
> 
> A possible patch for 4.7 would be like the attached (untested) patch.

Let's simply declare this as WONTFIX on the 4.7 branch.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-13  9:37                   ` Eric Botcazou
@ 2013-09-13  9:48                     ` Bernd Edlinger
  0 siblings, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-13  9:48 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Richard Biener, Martin Jambor

>> While it is straight forward to remove the movmisalign path in 4.9 and 4.8,
>> this is not so simple in the 4.7 branch. The reason is that 4.7 uses
>> "to_rtx = expand_normal (tem);" while 4.8 and 4.9 use
>> "to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);"
>> which does almost the same, but returns the misaligned rtx instead of
>> an register with the value of the structure. And the generated code without
>> the misalign path fails simply because the assignment goes to the register
>> instead of the structure.
>>
>> So the problem is: there is no EXPAND_WRITE/EXPAND_MEMORY in 4.7...
>>
>> A possible patch for 4.7 would be like the attached (untested) patch.
>
> Let's simply declare this as WONTFIX on the 4.7 branch.
>
> --
> Eric Botcazou

I absolutely agree with you. This was only meant as a theoretical exercise.

I was just nervous, if removing the misalign path is the right fix here,
because as Martin pointed out that SRA behaves quite differently
in the 4.7 branch, and pr50444.c does test nothing in 4.8 and trunk.

The result is: yes. Removing the misalign path will be OK on trunk.

Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-11 14:47               ` Richard Biener
  2013-09-12 21:07                 ` Bernd Edlinger
@ 2013-09-15 19:08                 ` Bernd Edlinger
  2013-09-17  0:05                   ` Martin Jambor
  2013-09-17 11:07                   ` [PATCH, PR 57748] Check for out of bounds access Richard Biener
  1 sibling, 2 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-15 19:08 UTC (permalink / raw)
  To: Richard Biener; +Cc: Martin Jambor, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 679 bytes --]

Hello Richard,

attached is my second attempt at fixing PR 57748. This time the movmisalign
path is completely removed and a similar bug in the read handling of misaligned
structures with a non-BLKmode is fixed too. There are several new test cases for the
different possible failure modes.

This patch was boot-strapped and regression tested on  x86_64-unknown-linux-gnu
and i686-pc-linux-gnu.

Additionally I generated eCos and an eCos-application (on ARMv5 using packed
structures) with an arm-eabi cross compiler, and looked for differences in the
disassembled code with and without this patch, but there were none.

OK for trunk?

Regards
Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748.txt --]
[-- Type: text/plain, Size: 519 bytes --]

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

	PR middle-end/57748
	* expr.c (expand_assignment): Remove misalignp code path.
	Check for bitregion in offset arithmetic.
	(expand_expr_real_1): Use EXAND_MEMORY on base object.

testsuite:

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


[-- Attachment #3: patch-pr57748.diff --]
[-- Type: application/octet-stream, Size: 8061 bytes --]

--- gcc/expr.c	2013-08-06 00:09:45.000000000 +0200
+++ gcc/expr.c	2013-09-10 08:23:09.570951685 +0200
@@ -4691,8 +4691,6 @@ expand_assignment (tree to, tree from, b
       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,
@@ -4702,40 +4700,7 @@ expand_assignment (tree to, tree from, b
 	  && 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.
@@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
 	  if (MEM_P (to_rtx)
 	      && GET_MODE (to_rtx) == BLKmode
 	      && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
+	      && bitregion_start == 0
+	      && bitregion_end == 0
 	      && bitsize > 0
 	      && (bitpos % bitsize) == 0
 	      && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
@@ -4874,17 +4841,6 @@ expand_assignment (tree to, tree from, b
 				  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 ();
@@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target
 			  && modifier != EXPAND_STACK_PARM
 			  ? target : NULL_RTX),
 			 VOIDmode,
-			 modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+			 EXPAND_MEMORY);
 
 	/* If the bitfield is volatile, we want to access it in the
 	   field's mode, not the computed mode.
--- gcc/testsuite/gcc.dg/torture/pr57748-1.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-1.c	2013-09-06 08:38:03.718686940 +0200
@@ -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;
+}
--- gcc/testsuite/gcc.dg/torture/pr57748-2.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-2.c	2013-09-06 08:38:03.718686940 +0200
@@ -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;
+}
--- gcc/testsuite/gcc.dg/torture/pr57748-3.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-3.c	2013-09-13 12:46:34.456009224 +0200
@@ -0,0 +1,48 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* data store race in expand_assignment:
+   misalignp == true, !MEM_P (to_rtx),
+   offset == 0, bitsize < GET_MODE_BITSIZE,
+   => rmw cycle on MEM.  */
+
+extern void abort (void);
+
+typedef long long V
+  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+union x
+{
+  long long a;
+  float b;
+} __attribute__((aligned (1)));
+
+struct s
+{
+  union x xx[0];
+  V x;
+} __attribute__((packed));
+
+void __attribute__((noinline, noclone))
+check (union x *xx)
+{
+  if (xx[0].b != 3.14F || xx[1].a != 0x123456789ABCDEF)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct s * x)
+{
+  x->xx[0].a = -1;
+  x->xx[0].b = 3.14F;
+  x->x[1] = 0x123456789ABCDEF;
+}
+
+struct s ss;
+
+int
+main ()
+{
+  foo (&ss);
+  check (ss.xx);
+  return 0;
+}
--- gcc/testsuite/gcc.dg/torture/pr57748-3a.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-3a.c	2013-09-13 12:44:47.140007819 +0200
@@ -0,0 +1,7 @@
+/* PR middle-end/57748 */
+/* { dg-do compile } */
+/* { dg-options "-msse2" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-assembler-not "movdqu" } } */
+/* { dg-final { scan-assembler-not "movdqa" } } */
+#include "pr57748-3.c"
--- gcc/testsuite/gcc.dg/torture/pr57748-4.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-4.c	2013-09-13 12:46:13.412008952 +0200
@@ -0,0 +1,49 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1:
+   read whole structure instead of only one member.  */
+
+extern void abort (void);
+
+typedef long long V
+  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+union x
+{
+  long long a;
+  float b;
+} __attribute__((aligned (1)));
+
+struct s
+{
+  union x xx[0];
+  V x;
+} __attribute__((packed));
+
+void __attribute__((noinline, noclone))
+check (struct s *x)
+{
+  if (x->xx[0].b != 3.14F || x->xx[1].a != 0x123456789ABCDEF)
+    abort ();
+  if (x->xx[2].b != 3.14F || x->xx[3].a != 0x123456789ABCDEF)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct s * x)
+{
+  x->xx[0].a = -1;
+  x->xx[0].b = 3.14F;
+  x->x[1] = 0x123456789ABCDEF;
+}
+
+struct s ss[2];
+
+int
+main ()
+{
+  foo (ss);
+  foo (ss+1);
+  check (ss);
+  return 0;
+}
--- gcc/testsuite/gcc.dg/torture/pr57748-4a.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-4a.c	2013-09-13 12:46:02.812008813 +0200
@@ -0,0 +1,7 @@
+/* PR middle-end/57748 */
+/* { dg-do compile } */
+/* { dg-options "-msse2" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-assembler-not "movdqu" } } */
+/* { dg-final { scan-assembler-not "movdqa" } } */
+#include "pr57748-4.c"

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-15 19:08                 ` Bernd Edlinger
@ 2013-09-17  0:05                   ` Martin Jambor
  2013-09-17 10:32                     ` Bernd Edlinger
  2013-10-22 14:08                     ` Bernd Edlinger
  2013-09-17 11:07                   ` [PATCH, PR 57748] Check for out of bounds access Richard Biener
  1 sibling, 2 replies; 105+ messages in thread
From: Martin Jambor @ 2013-09-17  0:05 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Richard Biener, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 3446 bytes --]

Hi,

On Sun, Sep 15, 2013 at 06:55:17PM +0200, Bernd Edlinger wrote:
> Hello Richard,
> 
> attached is my second attempt at fixing PR 57748. This time the
> movmisalign path is completely removed and a similar bug in the read
> handling of misaligned structures with a non-BLKmode is fixed
> too. There are several new test cases for the different possible
> failure modes.

I think the third and fourth testcases are undefined as the
description of zero-length arrays extension clearly says the whole
thing only makes sense when used as the last field of the
outermost-aggregate type.  I have not really understood what the third
testcase is supposed to test but I did not try too much.  Instead of
the fourth testcase, you can demonstrate the need for your change in
expand_expr_real_1 by augmenting the original testcase a little like
in attached pr57748-m1.c.

The hunk in expand_expr_real_1 can prove problematic if at any point
we need to pass some other modifier to the expansion of tem.  I'll try
to see if I can come up with a testcase tomorrow.  But perhaps we
never do (and can hope we never will) and then it would be sort of
OKish (note that I cannot approve anything) even though it can
pessimize unaligned access paths (by not using movmisalign_optab even
when perfectly possible - which is always when there is no zero sized
array).  It really just shows how evil non-BLKmode structures with
zero-sized arrays are and how they complicate things.  The expansion
of component_refs is reasonably built around the assumption that we'd
expand the structure in its mode in the most efficient manner and then
chuck the correct part out of it, but here we need to tell the
expansion of the structure to hold itself back because we'll be
looking outside of the structure (as specified by mode).

I'm not sure to what extent the hunk adding tests for bitregion_start
and bitregion_end being zero is connected to this issue.  I do not see
any of the testcases exercising that path.  If it is indeed another
problem, I think it should be submitted (and potentially committed) as
a separate patch, preferably with a testcase.

Having said all that, I think that removing the misalignp path from
expand_assignment altogether is a good idea.  I have verified that
when the expander is now presented with basically the same thing that
4.7 choked on, expand_expr (..., EXPAND_WRITE) can cope with it (see
attached file c.c) and doing that simplifies this complex code path.

Thanks,

Martin

> 
> This patch was boot-strapped and regression tested on  x86_64-unknown-linux-gnu
> and i686-pc-linux-gnu.
> 
> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
> structures) with an arm-eabi cross compiler, and looked for differences in the
> disassembled code with and without this patch, but there were none.
> 
> OK for trunk?
> 
> Regards
> Bernd. 		 	   		  

> 2013-09-15  Bernd Edlinger  <bernd.edlinger@hotmail.de>
> 
> 	PR middle-end/57748
> 	* expr.c (expand_assignment): Remove misalignp code path.
> 	Check for bitregion in offset arithmetic.
> 	(expand_expr_real_1): Use EXAND_MEMORY on base object.
> 
> testsuite:
> 
> 	PR middle-end/57748
> 	* gcc.dg/torture/pr57748-1.c: New test.
> 	* gcc.dg/torture/pr57748-2.c: New test.
> 	* gcc.dg/torture/pr57748-3.c: New test.
> 	* gcc.dg/torture/pr57748-3a.c: New test.
> 	* gcc.dg/torture/pr57748-4.c: New test.
> 	* gcc.dg/torture/pr57748-4a.c: New test.
> 



[-- Attachment #2: pr57748-m1.c --]
[-- Type: text/x-c, Size: 842 bytes --]

/* PR middle-end/57748 */
/* { dg-do run } */

#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))
check_1 (P *p)
{
  if (p->b[0][0] != 3 || p->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 *) malloc (128);

  foo (&t->s);
  check (t);
  check_1 (&t->s);

  return 0;
}

[-- Attachment #3: c.c --]
[-- Type: text/x-c, Size: 421 bytes --]

#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; } P __attribute__((aligned (1)));

struct __attribute__((packed)) T { char c; P s; };

void __attribute__((noinline, noclone))
foo (P *p)
{
  V a = { 3, 4 };
  p->a = a;
}

int
main ()
{
  struct T *t = (struct T *) malloc (128);
  foo (&t->s);
  return 0;
}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-17  0:05                   ` Martin Jambor
@ 2013-09-17 10:32                     ` Bernd Edlinger
  2013-10-22 14:08                     ` Bernd Edlinger
  1 sibling, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-17 10:32 UTC (permalink / raw)
  To: Martin Jambor; +Cc: Richard Biener, GCC Patches

Hi Martin,

On Tue, 17 Sep 2013 01:09:45, Martin Jambor wrote:
> Hi,
>
> On Sun, Sep 15, 2013 at 06:55:17PM +0200, Bernd Edlinger wrote:
>> Hello Richard,
>>
>> attached is my second attempt at fixing PR 57748. This time the
>> movmisalign path is completely removed and a similar bug in the read
>> handling of misaligned structures with a non-BLKmode is fixed
>> too. There are several new test cases for the different possible
>> failure modes.
>
> I think the third and fourth testcases are undefined as the
> description of zero-length arrays extension clearly says the whole
> thing only makes sense when used as the last field of the
> outermost-aggregate type. I have not really understood what the third
> testcase is supposed to test but I did not try too much. Instead of
> the fourth testcase, you can demonstrate the need for your change in
> expand_expr_real_1 by augmenting the original testcase a little like
> in attached pr57748-m1.c.

The third test case tries to demonstrate the possible write data store
race (by checking the assembler output). But you are right, this example
is probably not valid C at all.

I was actually worried about unions with non-BLK mode and
a movmisalign optab handler.

When you look at stor-layout.c (compute_record_mode)
you'll see, that in the case of a union usually an integer mode is chosen,
which is exactly the same size as the whole union.
And just by chance this does not have a movmisalign optab.

Therefore I tried to cheat with that zero-sized array, which should
probably be rejected at stor-layout.c in the first place.

When I tried to make a test case out of it, the bug on the read side hit
me as a total surprise...

> The hunk in expand_expr_real_1 can prove problematic if at any point
> we need to pass some other modifier to the expansion of tem. I'll try
> to see if I can come up with a testcase tomorrow. But perhaps we
> never do (and can hope we never will) and then it would be sort of
> OKish (note that I cannot approve anything) even though it can
> pessimize unaligned access paths (by not using movmisalign_optab even
> when perfectly possible - which is always when there is no zero sized
> array). It really just shows how evil non-BLKmode structures with
> zero-sized arrays are and how they complicate things. The expansion
> of component_refs is reasonably built around the assumption that we'd
> expand the structure in its mode in the most efficient manner and then
> chuck the correct part out of it, but here we need to tell the
> expansion of the structure to hold itself back because we'll be
> looking outside of the structure (as specified by mode).

I too am under the very strong impression that this was not the intention
of the design to use a non-BLKmode on a structure with zero-sized arrays.

> I'm not sure to what extent the hunk adding tests for bitregion_start
> and bitregion_end being zero is connected to this issue. I do not see
> any of the testcases exercising that path. If it is indeed another
> problem, I think it should be submitted (and potentially committed) as
> a separate patch, preferably with a testcase.

Yes, you're probably right. I was unable to find a test case where this
code path executes with bitregions. As I said, it maybe possible to prove that
bitregion_start and bitregion_end == 0 if the other conditions are satisfied.
What is obvious, that it would cause problems to set bitpos=0 when
bitregion_start/end is pointing elsewhere.
It is however much easier to prove that not going into that code path
would not cause any problems if bitregion_start/end is not zero.

So this was just for safer programming, but probably no real bug.


Thanks,
Bernd.

> Having said all that, I think that removing the misalignp path from
> expand_assignment altogether is a good idea. I have verified that
> when the expander is now presented with basically the same thing that
> 4.7 choked on, expand_expr (..., EXPAND_WRITE) can cope with it (see
> attached file c.c) and doing that simplifies this complex code path.
>
> Thanks,
>
> Martin
>
>>
>> This patch was boot-strapped and regression tested on  x86_64-unknown-linux-gnu
>> and i686-pc-linux-gnu.
>>
>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
>> structures) with an arm-eabi cross compiler, and looked for differences in the
>> disassembled code with and without this patch, but there were none.
>>
>> OK for trunk?
>>
>> Regards
>> Bernd.
>
>> 2013-09-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>>
>> PR middle-end/57748
>> * expr.c (expand_assignment): Remove misalignp code path.
>> Check for bitregion in offset arithmetic.
>> (expand_expr_real_1): Use EXAND_MEMORY on base object.
>>
>> testsuite:
>>
>> PR middle-end/57748
>> * gcc.dg/torture/pr57748-1.c: New test.
>> * gcc.dg/torture/pr57748-2.c: New test.
>> * gcc.dg/torture/pr57748-3.c: New test.
>> * gcc.dg/torture/pr57748-3a.c: New test.
>> * gcc.dg/torture/pr57748-4.c: New test.
>> * gcc.dg/torture/pr57748-4a.c: New test.
>>
>
> 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-15 19:08                 ` Bernd Edlinger
  2013-09-17  0:05                   ` Martin Jambor
@ 2013-09-17 11:07                   ` Richard Biener
  2013-09-17 11:41                     ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Richard Biener @ 2013-09-17 11:07 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches

On Sun, Sep 15, 2013 at 6:55 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hello Richard,
>
> attached is my second attempt at fixing PR 57748. This time the movmisalign
> path is completely removed and a similar bug in the read handling of misaligned
> structures with a non-BLKmode is fixed too. There are several new test cases for the
> different possible failure modes.
>
> This patch was boot-strapped and regression tested on  x86_64-unknown-linux-gnu
> and i686-pc-linux-gnu.
>
> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
> structures) with an arm-eabi cross compiler, and looked for differences in the
> disassembled code with and without this patch, but there were none.
>
> OK for trunk?

I agree that the existing movmisaling path that you remove is simply bogus, so
removing it looks fine to me.  Can you give rationale to

@@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
          if (MEM_P (to_rtx)
              && GET_MODE (to_rtx) == BLKmode
              && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
+             && bitregion_start == 0
+             && bitregion_end == 0
              && bitsize > 0
              && (bitpos % bitsize) == 0
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0

and especially to

@@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target
                          && modifier != EXPAND_STACK_PARM
                          ? target : NULL_RTX),
                         VOIDmode,
-                        modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+                        EXPAND_MEMORY);

        /* If the bitfield is volatile, we want to access it in the
           field's mode, not the computed mode.

which AFAIK makes "memory" expansion of loads/stores from/to registers
change (fail? go through stack memory?) - see handling of non-MEM return
values from that expand_expr call.

That is, do you see anything break with just removing the movmisalign path?
I'd rather install that (with the new testcases that then pass) separately as
this is a somewhat fragile area and being able to more selectively
bisect/backport
would be nice.

Thanks,
Richard.

> Regards
> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-17 11:07                   ` [PATCH, PR 57748] Check for out of bounds access Richard Biener
@ 2013-09-17 11:41                     ` Richard Biener
  2013-09-17 12:48                       ` Bernd Edlinger
  2013-09-24  6:34                       ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger
  0 siblings, 2 replies; 105+ messages in thread
From: Richard Biener @ 2013-09-17 11:41 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches

On Tue, Sep 17, 2013 at 12:00 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Sun, Sep 15, 2013 at 6:55 PM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
>> Hello Richard,
>>
>> attached is my second attempt at fixing PR 57748. This time the movmisalign
>> path is completely removed and a similar bug in the read handling of misaligned
>> structures with a non-BLKmode is fixed too. There are several new test cases for the
>> different possible failure modes.
>>
>> This patch was boot-strapped and regression tested on  x86_64-unknown-linux-gnu
>> and i686-pc-linux-gnu.
>>
>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
>> structures) with an arm-eabi cross compiler, and looked for differences in the
>> disassembled code with and without this patch, but there were none.
>>
>> OK for trunk?
>
> I agree that the existing movmisaling path that you remove is simply bogus, so
> removing it looks fine to me.  Can you give rationale to
>
> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
>           if (MEM_P (to_rtx)
>               && GET_MODE (to_rtx) == BLKmode
>               && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
> +             && bitregion_start == 0
> +             && bitregion_end == 0
>               && bitsize > 0
>               && (bitpos % bitsize) == 0
>               && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
>
> and especially to
>
> @@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target
>                           && modifier != EXPAND_STACK_PARM
>                           ? target : NULL_RTX),
>                          VOIDmode,
> -                        modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
> +                        EXPAND_MEMORY);
>
>         /* If the bitfield is volatile, we want to access it in the
>            field's mode, not the computed mode.
>
> which AFAIK makes "memory" expansion of loads/stores from/to registers
> change (fail? go through stack memory?) - see handling of non-MEM return
> values from that expand_expr call.

In particular this seems to disable all movmisalign handling for MEM_REFs
wrapped in component references which looks wrong.  I was playing with

typedef long long V
  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));

struct S { long long a[11]; V v; }__attribute__((aligned(8),packed)) ;
struct S a, *b = &a;
V v, w;

int main()
{
  v = b->v;
  b->v = w;
  return 0;
}

(use -fno-common) and I see that we use unaligned stores too often
(even with a properly aligned MEM).

The above at least shows movmisalign opportunities wrapped in component-refs.

> That is, do you see anything break with just removing the movmisalign path?
> I'd rather install that (with the new testcases that then pass) separately as
> this is a somewhat fragile area and being able to more selectively
> bisect/backport
> would be nice.
>
> Thanks,
> Richard.
>
>> Regards
>> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-17 11:41                     ` Richard Biener
@ 2013-09-17 12:48                       ` Bernd Edlinger
  2013-09-24 11:40                         ` Richard Biener
  2013-09-24  6:34                       ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-17 12:48 UTC (permalink / raw)
  To: Richard Biener; +Cc: Martin Jambor, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 4893 bytes --]

On Tue, 17 Sep 2013 12:45:40, Richard Biener wrote:
>
> On Tue, Sep 17, 2013 at 12:00 PM, Richard Biener
> <richard.guenther@gmail.com> wrote:
>> On Sun, Sep 15, 2013 at 6:55 PM, Bernd Edlinger
>> <bernd.edlinger@hotmail.de> wrote:
>>> Hello Richard,
>>>
>>> attached is my second attempt at fixing PR 57748. This time the movmisalign
>>> path is completely removed and a similar bug in the read handling of misaligned
>>> structures with a non-BLKmode is fixed too. There are several new test cases for the
>>> different possible failure modes.
>>>
>>> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu
>>> and i686-pc-linux-gnu.
>>>
>>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
>>> structures) with an arm-eabi cross compiler, and looked for differences in the
>>> disassembled code with and without this patch, but there were none.
>>>
>>> OK for trunk?
>>
>> I agree that the existing movmisaling path that you remove is simply bogus, so
>> removing it looks fine to me. Can you give rationale to
>>
>> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
>> if (MEM_P (to_rtx)
>> && GET_MODE (to_rtx) == BLKmode
>> && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
>> + && bitregion_start == 0
>> + && bitregion_end == 0
>> && bitsize> 0
>> && (bitpos % bitsize) == 0
>> && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0

OK, as already said, I think it could be dangerous to set bitpos=0 without
considering bitregion_start/end, but I think it may be possible that this
can not happen, because if bitsize is a multiple if ALIGNMENT, and
bitpos is a multiple of bitsize, we probably do not have a bit-field at all.
And of course I have no test case that fails without this hunk.
Maybe it would be better to add an assertion here like:

  {
      gcc_assert (bitregion_start == 0 && bitregion_end == 0);
      to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
      bitpos = 0;
  }

>> and especially to
>>
>> @@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target
>> && modifier != EXPAND_STACK_PARM
>> ? target : NULL_RTX),
>> VOIDmode,
>> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
>> + EXPAND_MEMORY);
>>
>> /* If the bitfield is volatile, we want to access it in the
>> field's mode, not the computed mode.
>>
>> which AFAIK makes "memory" expansion of loads/stores from/to registers
>> change (fail? go through stack memory?) - see handling of non-MEM return
>> values from that expand_expr call.

I wanted to make the expansion of MEM_REF and TARGET_MEM_REF
not go thru the final misalign handling, which is guarded by
"if (modifier != EXPAND_WRITE  && modifier != EXPAND_MEMORY && ..."

What we want here is most likely EXPAND_MEMORY, which returns a
memory context if possible.

Could you specify more explicitly what you mean with "handling of non-MEM return
values from that expand_expr call", then I could try finding test cases for
that.


> In particular this seems to disable all movmisalign handling for MEM_REFs
> wrapped in component references which looks wrong. I was playing with
>
> typedef long long V
> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
>
> struct S { long long a[11]; V v; }__attribute__((aligned(8),packed)) ;
> struct S a, *b = &a;
> V v, w;
>
> int main()
> {
> v = b->v;
> b->v = w;
> return 0;
> }
>
> (use -fno-common) and I see that we use unaligned stores too often
> (even with a properly aligned MEM).
>
> The above at least shows movmisalign opportunities wrapped in component-refs.

hmm, interesting. This does not compile differently with or without this patch.

I have another observation, regarding the testcase pr50444.c:

method:
.LFB4:
        .cfi_startproc
        movq    32(%rdi), %rax
        testq   %rax, %rax
        jne     .L7
        addl    $1, 16(%rdi)
        movl    $3, %eax
        movq    %rax, 32(%rdi)
        movdqu  16(%rdi), %xmm0
        pxor    (%rdi), %xmm0
        movdqu  %xmm0, 40(%rdi)

here the first movdqu could as well be movdqa, because 16+rdi is 128-bit aligned.
In the ctor method a movdqa is used, but the SRA is very pessimistic and generates
an unaligned MEM_REF. Also this example does not compile any different with this patch.


>> That is, do you see anything break with just removing the movmisalign path?
>> I'd rather install that (with the new testcases that then pass) separately as
>> this is a somewhat fragile area and being able to more selectively
>> bisect/backport
>> would be nice.

No, I think that is a good idea.

Attached the first part of the patch, that does only remove the movmisalign path.

Should I apply this one after regression testing?

Bernd.

>> Thanks,
>> Richard.
>>
>>> Regards
>>> Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748.txt --]
[-- Type: text/plain, Size: 254 bytes --]

2013-09-17  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.


[-- Attachment #3: patch-pr57748.diff --]
[-- Type: application/octet-stream, Size: 4437 bytes --]

--- gcc/expr.c	2013-09-12 15:03:18.000000000 +0200
+++ gcc/expr.c	2013-09-17 13:13:45.762823753 +0200
@@ -4709,8 +4709,6 @@ expand_assignment (tree to, tree from, b
       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, b
 	  && 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, b
 				  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 ();
--- gcc/testsuite/gcc.dg/torture/pr57748-1.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-1.c	2013-09-06 08:38:03.718686940 +0200
@@ -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;
+}
--- gcc/testsuite/gcc.dg/torture/pr57748-2.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/pr57748-2.c	2013-09-06 08:38:03.718686940 +0200
@@ -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;
+}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-17 11:41                     ` Richard Biener
  2013-09-17 12:48                       ` Bernd Edlinger
@ 2013-09-24  6:34                       ` Bernd Edlinger
  2013-09-24 10:31                         ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-24  6:34 UTC (permalink / raw)
  To: Richard Biener; +Cc: Martin Jambor, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 624 bytes --]

Hi,

with the attached patch the read-side of the out of bounds accesses are fixed.
There is a single new test case pr57748-3.c that is derived from Martin's test case.
The test case does only test the read access and does not depend on part 1 of the
patch.

This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu.

Additionally I generated eCos and an eCos-application (on ARMv5 using packed
structures) with an arm-eabi cross compiler, and looked for differences in the
disassembled code with and without this patch, but there were none.

OK for trunk?


Regards
Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748-2.txt --]
[-- Type: text/plain, Size: 219 bytes --]

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

	PR middle-end/57748
	* expr.c (expand_expr_real_1): Use EXAND_MEMORY on base object.

testsuite/

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


[-- Attachment #3: patch-pr57748-2.diff --]
[-- Type: application/octet-stream, Size: 1399 bytes --]

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 202778)
+++ gcc/expr.c	(working copy)
@@ -9878,7 +9878,7 @@
 			  && modifier != EXPAND_STACK_PARM
 			  ? target : NULL_RTX),
 			 VOIDmode,
-			 modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+			 EXPAND_MEMORY);
 
 	/* If the bitfield is volatile, we want to access it in the
 	   field's mode, not the computed mode.
Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
@@ -0,0 +1,40 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#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 (P *p)
+{
+  if (p->b[0][0] != 3 || p->b[0][1] != 4)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct T *t)
+{
+  V a = { 3, 4 };
+  t->s.b[0] = a;
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+
+  foo (t);
+  check (&t->s);
+
+  free (t);
+  return 0;
+}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-24  6:34                       ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger
@ 2013-09-24 10:31                         ` Richard Biener
  2013-09-24 14:46                           ` Eric Botcazou
  2013-09-24 18:51                           ` Martin Jambor
  0 siblings, 2 replies; 105+ messages in thread
From: Richard Biener @ 2013-09-24 10:31 UTC (permalink / raw)
  To: Bernd Edlinger, Eric Botcazou; +Cc: Martin Jambor, GCC Patches

On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi,
>
> with the attached patch the read-side of the out of bounds accesses are fixed.
> There is a single new test case pr57748-3.c that is derived from Martin's test case.
> The test case does only test the read access and does not depend on part 1 of the
> patch.
>
> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu.
>
> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
> structures) with an arm-eabi cross compiler, and looked for differences in the
> disassembled code with and without this patch, but there were none.
>
> OK for trunk?

Index: gcc/expr.c
===================================================================
--- gcc/expr.c  (revision 202778)
+++ gcc/expr.c  (working copy)
@@ -9878,7 +9878,7 @@
                          && modifier != EXPAND_STACK_PARM
                          ? target : NULL_RTX),
                         VOIDmode,
-                        modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+                        EXPAND_MEMORY);

        /* If the bitfield is volatile, we want to access it in the
           field's mode, not the computed mode.

context suggests that we may arrive with EXPAND_STACK_PARM here
which is a correctness modifier (see its docs).  But I'm not too familiar
with the details of the various expand modifiers, Eric may be though.

That said, I still believe that fixing the misalign path in expand_assignment
would be better than trying to avoid it.  For this testcase the issue is
again that expand_assignment passes the wrong mode/target to the
movmisalign optab.

Richard.

>
> Regards
> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-09-17 12:48                       ` Bernd Edlinger
@ 2013-09-24 11:40                         ` Richard Biener
  2013-09-24 11:56                           ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Richard Biener @ 2013-09-24 11:40 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches

On Tue, Sep 17, 2013 at 2:08 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> On Tue, 17 Sep 2013 12:45:40, Richard Biener wrote:
>>
>> On Tue, Sep 17, 2013 at 12:00 PM, Richard Biener
>> <richard.guenther@gmail.com> wrote:
>>> On Sun, Sep 15, 2013 at 6:55 PM, Bernd Edlinger
>>> <bernd.edlinger@hotmail.de> wrote:
>>>> Hello Richard,
>>>>
>>>> attached is my second attempt at fixing PR 57748. This time the movmisalign
>>>> path is completely removed and a similar bug in the read handling of misaligned
>>>> structures with a non-BLKmode is fixed too. There are several new test cases for the
>>>> different possible failure modes.
>>>>
>>>> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu
>>>> and i686-pc-linux-gnu.
>>>>
>>>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
>>>> structures) with an arm-eabi cross compiler, and looked for differences in the
>>>> disassembled code with and without this patch, but there were none.
>>>>
>>>> OK for trunk?
>>>
>>> I agree that the existing movmisaling path that you remove is simply bogus, so
>>> removing it looks fine to me. Can you give rationale to
>>>
>>> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
>>> if (MEM_P (to_rtx)
>>> && GET_MODE (to_rtx) == BLKmode
>>> && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
>>> + && bitregion_start == 0
>>> + && bitregion_end == 0
>>> && bitsize> 0
>>> && (bitpos % bitsize) == 0
>>> && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
>
> OK, as already said, I think it could be dangerous to set bitpos=0 without
> considering bitregion_start/end, but I think it may be possible that this
> can not happen, because if bitsize is a multiple if ALIGNMENT, and
> bitpos is a multiple of bitsize, we probably do not have a bit-field at all.
> And of course I have no test case that fails without this hunk.
> Maybe it would be better to add an assertion here like:
>
>   {
>       gcc_assert (bitregion_start == 0 && bitregion_end == 0);
>       to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
>       bitpos = 0;
>   }
>
>>> and especially to
>>>
>>> @@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target
>>> && modifier != EXPAND_STACK_PARM
>>> ? target : NULL_RTX),
>>> VOIDmode,
>>> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
>>> + EXPAND_MEMORY);
>>>
>>> /* If the bitfield is volatile, we want to access it in the
>>> field's mode, not the computed mode.
>>>
>>> which AFAIK makes "memory" expansion of loads/stores from/to registers
>>> change (fail? go through stack memory?) - see handling of non-MEM return
>>> values from that expand_expr call.
>
> I wanted to make the expansion of MEM_REF and TARGET_MEM_REF
> not go thru the final misalign handling, which is guarded by
> "if (modifier != EXPAND_WRITE  && modifier != EXPAND_MEMORY && ..."
>
> What we want here is most likely EXPAND_MEMORY, which returns a
> memory context if possible.
>
> Could you specify more explicitly what you mean with "handling of non-MEM return
> values from that expand_expr call", then I could try finding test cases for
> that.
>
>
>> In particular this seems to disable all movmisalign handling for MEM_REFs
>> wrapped in component references which looks wrong. I was playing with
>>
>> typedef long long V
>> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
>>
>> struct S { long long a[11]; V v; }__attribute__((aligned(8),packed)) ;
>> struct S a, *b = &a;
>> V v, w;
>>
>> int main()
>> {
>> v = b->v;
>> b->v = w;
>> return 0;
>> }
>>
>> (use -fno-common) and I see that we use unaligned stores too often
>> (even with a properly aligned MEM).
>>
>> The above at least shows movmisalign opportunities wrapped in component-refs.
>
> hmm, interesting. This does not compile differently with or without this patch.
>
> I have another observation, regarding the testcase pr50444.c:
>
> method:
> .LFB4:
>         .cfi_startproc
>         movq    32(%rdi), %rax
>         testq   %rax, %rax
>         jne     .L7
>         addl    $1, 16(%rdi)
>         movl    $3, %eax
>         movq    %rax, 32(%rdi)
>         movdqu  16(%rdi), %xmm0
>         pxor    (%rdi), %xmm0
>         movdqu  %xmm0, 40(%rdi)
>
> here the first movdqu could as well be movdqa, because 16+rdi is 128-bit aligned.
> In the ctor method a movdqa is used, but the SRA is very pessimistic and generates
> an unaligned MEM_REF. Also this example does not compile any different with this patch.
>
>
>>> That is, do you see anything break with just removing the movmisalign path?
>>> I'd rather install that (with the new testcases that then pass) separately as
>>> this is a somewhat fragile area and being able to more selectively
>>> bisect/backport
>>> would be nice.
>
> No, I think that is a good idea.
>
> Attached the first part of the patch, that does only remove the movmisalign path.
>
> Should I apply this one after regression testing?

It seems you already have...?

Richard.

> Bernd.
>
>>> Thanks,
>>> Richard.
>>>
>>>> Regards
>>>> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-24 11:40                         ` Richard Biener
@ 2013-09-24 11:56                           ` Bernd Edlinger
  0 siblings, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-24 11:56 UTC (permalink / raw)
  To: Richard Biener; +Cc: Martin Jambor, GCC Patches

On Tue, 24 Sep 2013 13:13:09, Richard Biener wrote:
>>>> That is, do you see anything break with just removing the movmisalign path?
>>>> I'd rather install that (with the new testcases that then pass) separately as
>>>> this is a somewhat fragile area and being able to more selectively
>>>> bisect/backport
>>>> would be nice.
>>
>> No, I think that is a good idea.
>>
>> Attached the first part of the patch, that does only remove the movmisalign path.
>>
>> Should I apply this one after regression testing?
>
> It seems you already have...?
>
> Richard.
>

yes, did I misunderstand this message?

--- Comment #40 from rguenther at suse dot de <rguenther at suse dot de> ---
On Wed, 18 Sep 2013, bernd.edlinger at hotmail dot de wrote:
 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57748
> 
> --- Comment #38 from Bernd Edlinger <bernd.edlinger at hotmail dot de> ---
> Richard,
> 
> I've split up the patch as requested:
> 
> Part 1 was posted here, but not yet approved:
> http://gcc.gnu.org/ml/gcc-patches/2013-09/msg01292.html
> 
> Just for the record, part 1 has been bootstrapped and regression tested.
> 
> For part 2:
> For simplicity I'd propose to use simply pass EXPAND_MEMORY here.
> These misaligned uses are quite rare hopefully.
> 
> I will replace my test cases 3+4 with Martin's test case,
> maybe without the get_i() because otherwise the test will die
> from the ICE before the check runs.
> 
> Will do this after Part 1 if you agree...
 
The issue is that we added the movmisaling-on-component-ref path
for _correctness_ reasons.  Now, if all misaligned accesses end up
being expanded using BLKmode moves then it probably works ok (but
then they are going to be horribly inefficent and wouldn't have
triggered the movmisaling path anyway ...).
 
But I'm willing to make the experiment - we've got plenty (well ...)
time to watch out for fallout of this change (and it does simplify
code, something I always like ;))
 
>> Bernd.
>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> Regards
>>>>> Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-24 10:31                         ` Richard Biener
@ 2013-09-24 14:46                           ` Eric Botcazou
  2013-09-24 18:51                           ` Martin Jambor
  1 sibling, 0 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-09-24 14:46 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor

> Index: gcc/expr.c
> ===================================================================
> --- gcc/expr.c  (revision 202778)
> +++ gcc/expr.c  (working copy)
> @@ -9878,7 +9878,7 @@
>                           && modifier != EXPAND_STACK_PARM
>                           ? target : NULL_RTX),
>                          VOIDmode,
> -                        modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
> +                        EXPAND_MEMORY);
> 
>         /* If the bitfield is volatile, we want to access it in the
>            field's mode, not the computed mode.
> 
> context suggests that we may arrive with EXPAND_STACK_PARM here
> which is a correctness modifier (see its docs).  But I'm not too familiar
> with the details of the various expand modifiers, Eric may be though.

Yes, this change looks far too bold and is presumably papering over the 
underlying issue...

> That said, I still believe that fixing the misalign path in
> expand_assignment would be better than trying to avoid it.  For this
> testcase the issue is again that expand_assignment passes the wrong
> mode/target to the
> movmisalign optab.

...then let's just fix the movmisalign stuff.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-24 10:31                         ` Richard Biener
  2013-09-24 14:46                           ` Eric Botcazou
@ 2013-09-24 18:51                           ` Martin Jambor
  2013-09-25  9:51                             ` Richard Biener
  2013-09-25 13:22                             ` Bernd Edlinger
  1 sibling, 2 replies; 105+ messages in thread
From: Martin Jambor @ 2013-09-24 18:51 UTC (permalink / raw)
  To: Richard Biener; +Cc: Bernd Edlinger, Eric Botcazou, GCC Patches

Hi,

On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote:
> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
> > Hi,
> >
> > with the attached patch the read-side of the out of bounds accesses are fixed.
> > There is a single new test case pr57748-3.c that is derived from Martin's test case.
> > The test case does only test the read access and does not depend on part 1 of the
> > patch.
> >
> > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu.
> >
> > Additionally I generated eCos and an eCos-application (on ARMv5 using packed
> > structures) with an arm-eabi cross compiler, and looked for differences in the
> > disassembled code with and without this patch, but there were none.
> >
> > OK for trunk?
> 
> Index: gcc/expr.c
> ===================================================================
> --- gcc/expr.c  (revision 202778)
> +++ gcc/expr.c  (working copy)
> @@ -9878,7 +9878,7 @@
>                           && modifier != EXPAND_STACK_PARM
>                           ? target : NULL_RTX),
>                          VOIDmode,
> -                        modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
> +                        EXPAND_MEMORY);
> 
>         /* If the bitfield is volatile, we want to access it in the
>            field's mode, not the computed mode.
> 
> context suggests that we may arrive with EXPAND_STACK_PARM here
> which is a correctness modifier (see its docs).  But I'm not too familiar
> with the details of the various expand modifiers, Eric may be though.
> 
> That said, I still believe that fixing the misalign path in expand_assignment
> would be better than trying to avoid it.  For this testcase the issue is
> again that expand_assignment passes the wrong mode/target to the
> movmisalign optab.

Perhaps I'm stating the obvious, but this is supposed to address a
separate bug in the expansion of the RHS (as opposed to the first bug
which was in the expansion of the LHS), and so we would have to make
expand_assignment to also examine potential misalignments in the RHS,
which it so far does not do, despite its complexity.

Having said that, I also dislike the patch, but I am quite convinced
that if we allow non-BLK structures with zero sized arrays, the fix
will be ugly - but I'll be glad to be shown I've been wrong.

Martin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-24 18:51                           ` Martin Jambor
@ 2013-09-25  9:51                             ` Richard Biener
  2013-09-25 14:56                               ` Martin Jambor
  2013-09-25 13:22                             ` Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Richard Biener @ 2013-09-25  9:51 UTC (permalink / raw)
  To: Richard Biener, Bernd Edlinger, Eric Botcazou, GCC Patches

On Tue, Sep 24, 2013 at 8:06 PM, Martin Jambor <mjambor@suse.cz> wrote:
> Hi,
>
> On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote:
>> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger
>> <bernd.edlinger@hotmail.de> wrote:
>> > Hi,
>> >
>> > with the attached patch the read-side of the out of bounds accesses are fixed.
>> > There is a single new test case pr57748-3.c that is derived from Martin's test case.
>> > The test case does only test the read access and does not depend on part 1 of the
>> > patch.
>> >
>> > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu.
>> >
>> > Additionally I generated eCos and an eCos-application (on ARMv5 using packed
>> > structures) with an arm-eabi cross compiler, and looked for differences in the
>> > disassembled code with and without this patch, but there were none.
>> >
>> > OK for trunk?
>>
>> Index: gcc/expr.c
>> ===================================================================
>> --- gcc/expr.c  (revision 202778)
>> +++ gcc/expr.c  (working copy)
>> @@ -9878,7 +9878,7 @@
>>                           && modifier != EXPAND_STACK_PARM
>>                           ? target : NULL_RTX),
>>                          VOIDmode,
>> -                        modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
>> +                        EXPAND_MEMORY);
>>
>>         /* If the bitfield is volatile, we want to access it in the
>>            field's mode, not the computed mode.
>>
>> context suggests that we may arrive with EXPAND_STACK_PARM here
>> which is a correctness modifier (see its docs).  But I'm not too familiar
>> with the details of the various expand modifiers, Eric may be though.
>>
>> That said, I still believe that fixing the misalign path in expand_assignment
>> would be better than trying to avoid it.  For this testcase the issue is
>> again that expand_assignment passes the wrong mode/target to the
>> movmisalign optab.
>
> Perhaps I'm stating the obvious, but this is supposed to address a
> separate bug in the expansion of the RHS (as opposed to the first bug
> which was in the expansion of the LHS), and so we would have to make
> expand_assignment to also examine potential misalignments in the RHS,
> which it so far does not do, despite its complexity.
>
> Having said that, I also dislike the patch, but I am quite convinced
> that if we allow non-BLK structures with zero sized arrays, the fix
> will be ugly - but I'll be glad to be shown I've been wrong.

I don't think the issues have anything to do with zero sized arrays
or non-BLK structures.  The issue is just we are feeding movmisaling
with the wrong mode (the mode of the base object) if we are expanding
a base object which is unaligned and has non-BLK mode.

So what we maybe need is another expand modifier that tells us
to not use movmisalign when expanding the base object.  Or we need
to stop expanding the base object with VOIDmode and instead pass
down the mode of the access (TYPE_MODE (TREE_TYPE (exp))
which will probably confuse other code.  So eventually not handling
the misaligned case by expansion of the base but inlined similar
to how it was in expand_assignment would be needed here.

Richard.

> Martin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-24 18:51                           ` Martin Jambor
  2013-09-25  9:51                             ` Richard Biener
@ 2013-09-25 13:22                             ` Bernd Edlinger
  1 sibling, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-25 13:22 UTC (permalink / raw)
  To: Martin Jambor, Richard Biener; +Cc: Eric Botcazou, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 5422 bytes --]

Hmm.....,

On Tue, 24 Sep 2013 20:06:51, Martin Jambor wrote:
> Hi,
>
> On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote:
>> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger
>> <bernd.edlinger@hotmail.de> wrote:
>>> Hi,
>>>
>>> with the attached patch the read-side of the out of bounds accesses are fixed.
>>> There is a single new test case pr57748-3.c that is derived from Martin's test case.
>>> The test case does only test the read access and does not depend on part 1 of the
>>> patch.
>>>
>>> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu.
>>>
>>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
>>> structures) with an arm-eabi cross compiler, and looked for differences in the
>>> disassembled code with and without this patch, but there were none.
>>>
>>> OK for trunk?
>>
>> Index: gcc/expr.c
>> ===================================================================
>> --- gcc/expr.c (revision 202778)
>> +++ gcc/expr.c (working copy)
>> @@ -9878,7 +9878,7 @@
>> && modifier != EXPAND_STACK_PARM
>> ? target : NULL_RTX),
>> VOIDmode,
>> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
>> + EXPAND_MEMORY);
>>
>> /* If the bitfield is volatile, we want to access it in the
>> field's mode, not the computed mode.
>>
>> context suggests that we may arrive with EXPAND_STACK_PARM here
>> which is a correctness modifier (see its docs). But I'm not too familiar
>> with the details of the various expand modifiers, Eric may be though.

"  EXPAND_STACK_PARM is used when expanding to a TARGET on  the stack for
   a call parameter.  Such targets require special care as we haven't yet
   marked TARGET so that it's safe from being trashed by libcalls.  We
   don't want to use TARGET for anything but the final result;
   Intermediate values must go elsewhere.   Additionally, calls to
   emit_block_move will be flagged with BLOCK_OP_CALL_PARM."

This should not be a problem: If modifier == EXPAND_STACK_PARM
the target is NOT passed down, and thus not giving the modifier either
should not cause incorrect code. But I might be wrong...

On the other hand, in the case where tem is a unaligned MEM_REF and
exp is not exactly the same object as tem,
EXPAND_STACK_PARM may exactly do the wrong thing.

What I can tell is, that this patch does not change a single bit in the complete
GCC boot strap process, stage 2 and stage 3 are binary identical with or
without this patch, and that all test cases pass, even the ADA test cases...


>> That said, I still believe that fixing the misalign path in expand_assignment
>> would be better than trying to avoid it. For this testcase the issue is
>> again that expand_assignment passes the wrong mode/target to the
>> movmisalign optab.
>
> Perhaps I'm stating the obvious, but this is supposed to address a
> separate bug in the expansion of the RHS (as opposed to the first bug
> which was in the expansion of the LHS), and so we would have to make
> expand_assignment to also examine potential misalignments in the RHS,
> which it so far does not do, despite its complexity.

Thanks for pointing that out. This is true.

> Having said that, I also dislike the patch, but I am quite convinced
> that if we allow non-BLK structures with zero sized arrays, the fix
> will be ugly - but I'll be glad to be shown I've been wrong.
>
> Martin

I could of course look at the type of tem, and only mess with the
expand modifier in case of a MEM_REF. But I am not sure what
to do about the VIEW_CONVERT_EXPR, if the code at normal_inner_ref
is wrong, the code at VIEW_CONVERT_EXPR can't possibly be any better,
although I have not yet any idea how to write a test case for this:

        /* ??? We should work harder and deal with non-zero offsets.  */
        if (!offset
            && (bitpos % BITS_PER_UNIT) == 0
            && bitsize>= 0
            && compare_tree_int (TYPE_SIZE (type), bitsize) == 0)
          {
            /* See the normal_inner_ref case for the rationale.  */
            orig_op0
              = expand_expr (tem,
                             (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
                              && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
                                  != INTEGER_CST)
                              && modifier != EXPAND_STACK_PARM
                              ? target : NULL_RTX),
                             VOIDmode,
                             modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);

Especially for EXPAND_STACK_PARM? If this does really allocate
something on a register, then the result will be thrown away, because
it is not MEM_P?
Right?


Note the RHS-Bug can also affect ordinary unions on ARM and all
STRICT_ALIGNMENT targets.

Please check the attached test case. It may not be obvious at
first sight, but the assembler code for check is definitely wrong,
because it reads the whole structure, and uses only one byte of it.
And that is, not OK because x was volatile...

check:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    stmfd    sp!, {r3, lr}
    mov    r3, #-2147483648
    ldr    r3, [r3, #2]    @ unaligned
    mov    r3, r3, lsr #24
    cmp    r3, #3
    ldmeqfd    sp!, {r3, pc}
    bl    abort


Bernd. 		 	   		  

[-- Attachment #2: pr57748-4.c --]
[-- Type: text/plain, Size: 459 bytes --]

/* PR middle-end/57748 */
/* arm-eabi-gcc -mcpu=cortex-a9 -O3 */

#include <stdlib.h>

union  x
{
  short a[2];
  char x[4];
} __attribute__((packed, aligned(4))) ;
typedef volatile union  x *s;

void __attribute__((noinline, noclone))
check (void)
{
  s xx=(s)(0x80000002);
  if (xx->x[3] != 3)
    abort ();
}

void __attribute__((noinline, noclone))
foo (void)
{
  s xx=(s)(0x80000002);
  xx->x[3] = 3;
}

int
main ()
{
  foo ();
  check ();
  return 0;
}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-25  9:51                             ` Richard Biener
@ 2013-09-25 14:56                               ` Martin Jambor
  2013-09-26  9:34                                 ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Martin Jambor @ 2013-09-25 14:56 UTC (permalink / raw)
  To: Richard Biener; +Cc: Bernd Edlinger, Eric Botcazou, GCC Patches

Hi,

On Wed, Sep 25, 2013 at 11:05:21AM +0200, Richard Biener wrote:
> On Tue, Sep 24, 2013 at 8:06 PM, Martin Jambor <mjambor@suse.cz> wrote:
> > Hi,
> >
> > On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote:
> >> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger
> >> <bernd.edlinger@hotmail.de> wrote:
> >> > Hi,
> >> >
> >> > with the attached patch the read-side of the out of bounds accesses are fixed.
> >> > There is a single new test case pr57748-3.c that is derived from Martin's test case.
> >> > The test case does only test the read access and does not depend on part 1 of the
> >> > patch.
> >> >
> >> > This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu.
> >> >
> >> > Additionally I generated eCos and an eCos-application (on ARMv5 using packed
> >> > structures) with an arm-eabi cross compiler, and looked for differences in the
> >> > disassembled code with and without this patch, but there were none.
> >> >
> >> > OK for trunk?
> >>
> >> Index: gcc/expr.c
> >> ===================================================================
> >> --- gcc/expr.c  (revision 202778)
> >> +++ gcc/expr.c  (working copy)
> >> @@ -9878,7 +9878,7 @@
> >>                           && modifier != EXPAND_STACK_PARM
> >>                           ? target : NULL_RTX),
> >>                          VOIDmode,
> >> -                        modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
> >> +                        EXPAND_MEMORY);
> >>
> >>         /* If the bitfield is volatile, we want to access it in the
> >>            field's mode, not the computed mode.
> >>
> >> context suggests that we may arrive with EXPAND_STACK_PARM here
> >> which is a correctness modifier (see its docs).  But I'm not too familiar
> >> with the details of the various expand modifiers, Eric may be though.
> >>
> >> That said, I still believe that fixing the misalign path in expand_assignment
> >> would be better than trying to avoid it.  For this testcase the issue is
> >> again that expand_assignment passes the wrong mode/target to the
> >> movmisalign optab.
> >
> > Perhaps I'm stating the obvious, but this is supposed to address a
> > separate bug in the expansion of the RHS (as opposed to the first bug
> > which was in the expansion of the LHS), and so we would have to make
> > expand_assignment to also examine potential misalignments in the RHS,
> > which it so far does not do, despite its complexity.
> >
> > Having said that, I also dislike the patch, but I am quite convinced
> > that if we allow non-BLK structures with zero sized arrays, the fix
> > will be ugly - but I'll be glad to be shown I've been wrong.
> 
> I don't think the issues have anything to do with zero sized arrays
> or non-BLK structures.  The issue is just we are feeding movmisaling
> with the wrong mode (the mode of the base object) if we are expanding
> a base object which is unaligned and has non-BLK mode.

I disagree.  Consider a slightly modified testcase:

#include <stdlib.h>
typedef long long V
  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));

#if 1
typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
struct __attribute__((packed)) T { char c; P s; };
#else
typedef struct S { V a; V b[0]; } P;
struct T { char c; P s; };
#endif

void __attribute__((noinline, noclone))
good_value (V b)
{
  if (b[0] != 3 || b[1] != 4)
    __builtin_abort ();
}

void __attribute__((noinline, noclone))
check (P *p)
{
  good_value (p->b[0]);
}

int
main ()
{
  struct T *t = (struct T *) calloc (128, 1);
  V a = { 3, 4 };
  t->s.b[0] = a;
  check (&t->s);
  free (t);
  return 0;
}

The problem is the expansion of the memory load in function check.
All involved modes, the one of the base structure and of the loaded
component, are V2DI so even if we somehow mixed them up, in this
example it should not matter, yet the unaligned load gives wrong
results.

I'm still convinced that the problem is that we have a V2DImode
structure which is larger that the mode tells and we want to load the
data from outside of its mode. That is only happening because zero
sized arrays.

> 
> So what we maybe need is another expand modifier that tells us
> to not use movmisalign when expanding the base object.

In that case we can just as well use EXPAND_MEMORY.  If so, I'd do
that only when there is a zero sized array involved in order not to
avoid using movmisalign when we can.

> Or we need to stop expanding the base object with VOIDmode and
> instead pass down the mode of the access (TYPE_MODE (TREE_TYPE
> (exp)) which will probably confuse other code. 

Well, because I think the problem is not (just) mixing up modes, I
don't think this will help either.

> So eventually not
> handling the misaligned case by expansion of the base but inlined
> similar to how it was in expand_assignment would be needed here.

At least now I fail to see how this would be different from copying a
large portion of expand_expr_real_1 (all of the MEM_REF part without
the movmisalign bit) and calling that when we detect "this case"
whatever we eventually agree it is.

Martin

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-25 14:56                               ` Martin Jambor
@ 2013-09-26  9:34                                 ` Bernd Edlinger
  2013-09-26 11:18                                   ` Eric Botcazou
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-26  9:34 UTC (permalink / raw)
  To: Martin Jambor, Richard Biener; +Cc: Eric Botcazou, GCC Patches

Hi,

On Wed, 25 Sep 2013 16:01:02, Martin Jambor wrote:
> Hi,
>
> On Wed, Sep 25, 2013 at 11:05:21AM +0200, Richard Biener wrote:
>> On Tue, Sep 24, 2013 at 8:06 PM, Martin Jambor <mjambor@suse.cz> wrote:
>>> Hi,
>>>
>>> On Tue, Sep 24, 2013 at 12:02:17PM +0200, Richard Biener wrote:
>>>> On Tue, Sep 24, 2013 at 4:52 AM, Bernd Edlinger
>>>> <bernd.edlinger@hotmail.de> wrote:
>>>>> Hi,
>>>>>
>>>>> with the attached patch the read-side of the out of bounds accesses are fixed.
>>>>> There is a single new test case pr57748-3.c that is derived from Martin's test case.
>>>>> The test case does only test the read access and does not depend on part 1 of the
>>>>> patch.
>>>>>
>>>>> This patch was boot-strapped and regression tested on x86_64-unknown-linux-gnu.
>>>>>
>>>>> Additionally I generated eCos and an eCos-application (on ARMv5 using packed
>>>>> structures) with an arm-eabi cross compiler, and looked for differences in the
>>>>> disassembled code with and without this patch, but there were none.
>>>>>
>>>>> OK for trunk?
>>>>
>>>> Index: gcc/expr.c
>>>> ===================================================================
>>>> --- gcc/expr.c (revision 202778)
>>>> +++ gcc/expr.c (working copy)
>>>> @@ -9878,7 +9878,7 @@
>>>> && modifier != EXPAND_STACK_PARM
>>>> ? target : NULL_RTX),
>>>> VOIDmode,
>>>> - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
>>>> + EXPAND_MEMORY);
>>>>
>>>> /* If the bitfield is volatile, we want to access it in the
>>>> field's mode, not the computed mode.
>>>>
>>>> context suggests that we may arrive with EXPAND_STACK_PARM here
>>>> which is a correctness modifier (see its docs). But I'm not too familiar
>>>> with the details of the various expand modifiers, Eric may be though.
>>>>
>>>> That said, I still believe that fixing the misalign path in expand_assignment
>>>> would be better than trying to avoid it. For this testcase the issue is
>>>> again that expand_assignment passes the wrong mode/target to the
>>>> movmisalign optab.
>>>
>>> Perhaps I'm stating the obvious, but this is supposed to address a
>>> separate bug in the expansion of the RHS (as opposed to the first bug
>>> which was in the expansion of the LHS), and so we would have to make
>>> expand_assignment to also examine potential misalignments in the RHS,
>>> which it so far does not do, despite its complexity.
>>>
>>> Having said that, I also dislike the patch, but I am quite convinced
>>> that if we allow non-BLK structures with zero sized arrays, the fix
>>> will be ugly - but I'll be glad to be shown I've been wrong.
>>
>> I don't think the issues have anything to do with zero sized arrays
>> or non-BLK structures. The issue is just we are feeding movmisaling
>> with the wrong mode (the mode of the base object) if we are expanding
>> a base object which is unaligned and has non-BLK mode.
>
> I disagree. Consider a slightly modified testcase:
>
> #include <stdlib.h>
> typedef long long V
> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
>
> #if 1
> typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
> struct __attribute__((packed)) T { char c; P s; };
> #else
> typedef struct S { V a; V b[0]; } P;
> struct T { char c; P s; };
> #endif
>
> void __attribute__((noinline, noclone))
> good_value (V b)
> {
> if (b[0] != 3 || b[1] != 4)
> __builtin_abort ();
> }
>
> void __attribute__((noinline, noclone))
> check (P *p)
> {
> good_value (p->b[0]);
> }
>
> int
> main ()
> {
> struct T *t = (struct T *) calloc (128, 1);
> V a = { 3, 4 };
> t->s.b[0] = a;
> check (&t->s);
> free (t);
> return 0;
> }
>
> The problem is the expansion of the memory load in function check.
> All involved modes, the one of the base structure and of the loaded
> component, are V2DI so even if we somehow mixed them up, in this
> example it should not matter, yet the unaligned load gives wrong
> results.
>
> I'm still convinced that the problem is that we have a V2DImode
> structure which is larger that the mode tells and we want to load the
> data from outside of its mode. That is only happening because zero
> sized arrays.

Yes, this is another good example, and it passes vector values on the
stack to a function. Again my patch produces working code, while
the current trunk produces just completely _insane_ code.

And again, this is not only a problem of structures with zero-sized
arrays at the end. Remember my previous example code:
On ARM (or anything with STRICT_ALIGNMENT) this union has the
same problems:

/* PR middle-end/57748 */
/* arm-eabi-gcc -mcpu=cortex-a9 -O3 */
#include <stdlib.h>

union  x
{
  short a[2];
  char x[4];
} __attribute__((packed, aligned(4))) ;
typedef volatile union  x *s;

void __attribute__((noinline, noclone))
check (void)
{
  s xx=(s)(0x80000002);
  /* although volatile xx->x[3] reads 4 bytes here */
  if (xx->x[3] != 3)
    abort ();
}

void __attribute__((noinline, noclone))
foo (void)
{
  s xx=(s)(0x80000002);
  xx->x[3] = 3;
}

int
main ()
{
  foo ();
  check ();
  return 0;
}


>>
>> So what we maybe need is another expand modifier that tells us
>> to not use movmisalign when expanding the base object.
>
> In that case we can just as well use EXPAND_MEMORY. If so, I'd do
> that only when there is a zero sized array involved in order not to
> avoid using movmisalign when we can.
>
>> Or we need to stop expanding the base object with VOIDmode and
>> instead pass down the mode of the access (TYPE_MODE (TREE_TYPE
>> (exp)) which will probably confuse other code.
>
> Well, because I think the problem is not (just) mixing up modes, I
> don't think this will help either.
>
>> So eventually not
>> handling the misaligned case by expansion of the base but inlined
>> similar to how it was in expand_assignment would be needed here.
>
> At least now I fail to see how this would be different from copying a
> large portion of expand_expr_real_1 (all of the MEM_REF part without
> the movmisalign bit) and calling that when we detect "this case"
> whatever we eventually agree it is.
>
> Martin

So I still think my patch does the right thing.

The rationale is:

          = expand_expr (tem,
                         (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
                          && COMPLETE_TYPE_P (TREE_TYPE (tem))
                          && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
                              != INTEGER_CST)
                          && modifier != EXPAND_STACK_PARM
                          ? target : NULL_RTX),
                         VOIDmode,
                         EXPAND_MEMORY);

returns the address of the structure in question,
we can add offset, bitoffset, and access the memory
in the right mode and alignment information is
passed to the backend via  MEM_ALIGN (op0).

Passing EXPAND_STACK_PARM would explicitly do the
wrong thing, as this is not the final result but only an
intermediate value.

As long as MEM_ALIGN(op0) is right it does not
matter if we use mov_optab or movmisalign_optab.

If _that_ is a bug, then the back-ends worked around it
already for years, and I don't see any reason for changing
that now.

Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-26  9:34                                 ` Bernd Edlinger
@ 2013-09-26 11:18                                   ` Eric Botcazou
  2013-09-26 12:42                                     ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-09-26 11:18 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> So I still think my patch does the right thing.
> 
> The rationale is:
> 
>           = expand_expr (tem,
>                          (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
>                           && COMPLETE_TYPE_P (TREE_TYPE (tem))
>                           && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
>                               != INTEGER_CST)
>                           && modifier != EXPAND_STACK_PARM
>                           ? target : NULL_RTX),
>                          VOIDmode,
>                          EXPAND_MEMORY);
> 
> returns the address of the structure in question,
> we can add offset, bitoffset, and access the memory
> in the right mode and alignment information is
> passed to the backend via  MEM_ALIGN (op0).

But there are conceptually no reasons to require a MEM here.  Look at all the 
code just below the block.  Given how hard it is to eliminate spills to memory 
in RTL once they are generated, this shouldn't be taken lightly.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-26 11:18                                   ` Eric Botcazou
@ 2013-09-26 12:42                                     ` Bernd Edlinger
  2013-09-27  8:45                                       ` Eric Botcazou
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-09-26 12:42 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener

Hi,

On Thu, 26 Sep 2013 11:34:02, Eric Botcazou wrote:
>
>> So I still think my patch does the right thing.
>>
>> The rationale is:
>>
>> = expand_expr (tem,
>> (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
>> && COMPLETE_TYPE_P (TREE_TYPE (tem))
>> && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
>> != INTEGER_CST)
>> && modifier != EXPAND_STACK_PARM
>> ? target : NULL_RTX),
>> VOIDmode,
>> EXPAND_MEMORY);
>>
>> returns the address of the structure in question,
>> we can add offset, bitoffset, and access the memory
>> in the right mode and alignment information is
>> passed to the backend via MEM_ALIGN (op0).
>
> But there are conceptually no reasons to require a MEM here. Look at all the
> code just below the block. Given how hard it is to eliminate spills to memory
> in RTL once they are generated, this shouldn't be taken lightly.
>
> --
> Eric Botcazou

Sure, but the modifier is not meant to force something into memory,
especially when it is already in an register. Remember, we are only
talking of structures here, and we only want to access one member.

It is more the other way round:
It says: "You do not have to load the value in a register, if it is already in
memory I'm happy"

At least in my understanding.

Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-26 12:42                                     ` Bernd Edlinger
@ 2013-09-27  8:45                                       ` Eric Botcazou
  2013-10-03  0:37                                         ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-09-27  8:45 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> Sure, but the modifier is not meant to force something into memory,
> especially when it is already in an register. Remember, we are only
> talking of structures here, and we only want to access one member.
> 
> It is more the other way round:
> It says: "You do not have to load the value in a register, if it is already
> in memory I'm happy"

   EXPAND_MEMORY means we are interested in a memory result, even if
    the memory is constant and we could have propagated a constant value.  */

We definitely want to propagate constant values here, look at the code below. 
And it already lists explicit cases where we really need to splill to memory.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-09-27  8:45                                       ` Eric Botcazou
@ 2013-10-03  0:37                                         ` Bernd Edlinger
  2013-10-08  8:02                                           ` Eric Botcazou
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-03  0:37 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 2820 bytes --]

Hi Eric,


On Fri, 27 Sep 2013 10:36:57, Eric Botcazou wrote:
>
>> Sure, but the modifier is not meant to force something into memory,
>> especially when it is already in an register. Remember, we are only
>> talking of structures here, and we only want to access one member.
>>
>> It is more the other way round:
>> It says: "You do not have to load the value in a register, if it is already
>> in memory I'm happy"
>
> EXPAND_MEMORY means we are interested in a memory result, even if
> the memory is constant and we could have propagated a constant value. */
>
> We definitely want to propagate constant values here, look at the code below.
> And it already lists explicit cases where we really need to splill to memory.
>
> --
> Eric Botcazou


I'd like to continue this discussion by proposing this updated patch.

I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
constant values.

I have done the same modification to VIEW_CONVERT_EXPR too, because
this is a possible inner reference, itself. It is however inherently hard to
test around this code.

To understand this patch it is good to know what type of object the
return value "tem" of get_inner_reference can be.

From the program logic at get_inner_reference it is clear that the
return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
further restricted because exp is gimplified.

Usually the result will be a MEM_REF or a SSA_NAME of the memory where
the structure is to be found.

When you look at where EXPAND_MEMORY is handled you see it is special-cased
in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
ARRAY_RANGE_REF.

At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
If it is an unaligned memory, we just return the unaligned reference.

This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
certainly be really hard to find test cases that exercise this code.

In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
we do not have to touch the handling of the outer modifier. However we pass
EXPAND_REFERENCE to the inner object, which should not be a recursive
use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.

TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.


OK, what do you think of it now?

Thanks
Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748-2.txt --]
[-- Type: text/plain, Size: 284 bytes --]

2013-10-03  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR middle-end/57748
	* expr.h (expand_modifier): New enum value EXPAND_REFERENCE.
	* expr.c (expand_expr_real_1): Use EXAND_REFERENCE on base object.

testsuite/

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


[-- Attachment #3: patch-pr57748-2.diff --]
[-- Type: application/octet-stream, Size: 4286 bytes --]

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 203044)
+++ gcc/expr.c	(working copy)
@@ -9573,6 +9573,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	align = get_object_alignment (exp);
 	if (modifier != EXPAND_WRITE
 	    && modifier != EXPAND_MEMORY
+	    && modifier != EXPAND_REFERENCE
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode)
 	    /* If the target does not have special handling for unaligned
@@ -9653,6 +9654,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	  MEM_VOLATILE_P (temp) = 1;
 	if (modifier != EXPAND_WRITE
 	    && modifier != EXPAND_MEMORY
+	    && modifier != EXPAND_REFERENCE
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode))
 	  {
@@ -9886,7 +9888,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 			  && modifier != EXPAND_STACK_PARM
 			  ? target : NULL_RTX),
 			 VOIDmode,
-			 modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+			 EXPAND_REFERENCE);
 
 	/* If the bitfield is volatile, we want to access it in the
 	   field's mode, not the computed mode.
@@ -10245,7 +10247,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 			      && modifier != EXPAND_STACK_PARM
 			      ? target : NULL_RTX),
 			     VOIDmode,
-			     modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+			     EXPAND_REFERENCE);
 
 	    if (MEM_P (orig_op0))
 	      {
@@ -10339,7 +10341,10 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	      op0 = copy_rtx (op0);
 	      set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
 	    }
-	  else if (mode != BLKmode
+	  else if (modifier != EXPAND_WRITE
+		   && modifier != EXPAND_MEMORY
+		   && modifier != EXPAND_REFERENCE
+		   && mode != BLKmode
 		   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)
 		   /* If the target does have special handling for unaligned
 		      loads of mode then use them.  */
@@ -10360,6 +10365,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	      return reg;
 	    }
 	  else if (STRICT_ALIGNMENT
+		   && modifier != EXPAND_WRITE
+		   && modifier != EXPAND_MEMORY
+		   && modifier != EXPAND_REFERENCE
 		   && mode != BLKmode
 		   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
 	    {
Index: gcc/expr.h
===================================================================
--- gcc/expr.h	(revision 203044)
+++ gcc/expr.h	(working copy)
@@ -41,10 +41,13 @@ along with GCC; see the file COPYING3.  If not see
     is a constant that is not a legitimate address.
    EXPAND_WRITE means we are only going to write to the resulting rtx.
    EXPAND_MEMORY means we are interested in a memory result, even if
-    the memory is constant and we could have propagated a constant value.  */
+    the memory is constant and we could have propagated a constant value,
+    or the memory is unaligned on a STRICT_ALIGNMENT target.
+   EXPAND_REFERENCE is similar to EXPAND_MEMORY, used internally to expand
+    the inner reference of a component.  */
 enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
 		      EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
-		      EXPAND_MEMORY};
+		      EXPAND_MEMORY, EXPAND_REFERENCE};
 
 /* Prevent the compiler from deferring stack pops.  See
    inhibit_defer_pop for more information.  */
Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
@@ -0,0 +1,40 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#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 (P *p)
+{
+  if (p->b[0][0] != 3 || p->b[0][1] != 4)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct T *t)
+{
+  V a = { 3, 4 };
+  t->s.b[0] = a;
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+
+  foo (t);
+  check (&t->s);
+
+  free (t);
+  return 0;
+}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-03  0:37                                         ` Bernd Edlinger
@ 2013-10-08  8:02                                           ` Eric Botcazou
  2013-10-08  9:22                                             ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-10-08  8:02 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> OK, what do you think of it now?

My take on this is that the Proper Fix(tm) has been posted by Martin:
  http://gcc.gnu.org/ml/gcc-patches/2013-08/msg00082.html
IMO it's a no-brainer, modulo the ABI concern.  Everything else is more or 
less clever stuff to paper over this original compute_record_mode bug.

We are lying to the expander by pretending that the object has V2DImode since 
it's larger and thus cannot be manipulated in this mode; everything is clearly
downhill from there.  If we don't want to properly fix the bug then let's put 
a hack in the expander, possibly using EXPAND_MEMORY, but it should trigger 
_only_ for structures with zero-sized arrays and non-BLKmode and be preceded 
by a big ??? comment explaining why it is deemed necessary.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-08  8:02                                           ` Eric Botcazou
@ 2013-10-08  9:22                                             ` Bernd Edlinger
  2013-10-08 21:04                                               ` Eric Botcazou
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-08  9:22 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener

Hi,

On Tue, 8 Oct 2013 10:01:37, Eric Botcazou wrote:
>
>> OK, what do you think of it now?
>
> My take on this is that the Proper Fix(tm) has been posted by Martin:
> http://gcc.gnu.org/ml/gcc-patches/2013-08/msg00082.html
> IMO it's a no-brainer, modulo the ABI concern. Everything else is more or
> less clever stuff to paper over this original compute_record_mode bug.
>
> We are lying to the expander by pretending that the object has V2DImode since
> it's larger and thus cannot be manipulated in this mode; everything is clearly
> downhill from there. If we don't want to properly fix the bug then let's put
> a hack in the expander, possibly using EXPAND_MEMORY, but it should trigger
> _only_ for structures with zero-sized arrays and non-BLKmode and be preceded
> by a big ??? comment explaining why it is deemed necessary.
>
> --
> Eric Botcazou

I agree, that assigning a non-BLKmode to structures with zero-sized arrays
should be considered a bug.

And it should be checked that there is only ONE zero-sized array.
And it should be checked that it is only allowed at the end of the structure.

Otherwise we have something like a union instead of a structure,
which will break the code in tree-ssa-alias.c !

And again, this is not only a problem of structures with zero-sized
arrays at the end. Remember my previous example code:
On ARM (or anything with STRICT_ALIGNMENT) this union has the
same problems:
 
/* PR middle-end/57748 */
/* arm-eabi-gcc -mcpu=cortex-a9 -O3 */
#include <stdlib.h>
 
union  x
{
  short a[2];
  char x[4];
} __attribute__((packed, aligned(4))) ;
typedef volatile union  x *s;
 
void __attribute__((noinline, noclone))
check (void)
{
  s xx=(s)(0x80000002);
  /* although volatile xx->x[3] reads 4 bytes here */
  if (xx->x[3] != 3)
    abort ();
}
 
void __attribute__((noinline, noclone))
foo (void)
{
  s xx=(s)(0x80000002);
  xx->x[3] = 3;
}
 
int
main ()
{
  foo ();
  check ();
  return 0;
}


This union has a UINT32 mode, look at compute_record_mode!
Because of this example I still think that the expander should know what
we intend to do with the base object.


Regards
Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-08  9:22                                             ` Bernd Edlinger
@ 2013-10-08 21:04                                               ` Eric Botcazou
  2013-10-08 23:03                                                 ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-10-08 21:04 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> I agree, that assigning a non-BLKmode to structures with zero-sized arrays
> should be considered a bug.

Fine, then let's apply Martin's patch, on mainline at least.

> And again, this is not only a problem of structures with zero-sized
> arrays at the end. Remember my previous example code:
> On ARM (or anything with STRICT_ALIGNMENT) this union has the
> same problems:
> 
> /* PR middle-end/57748 */
> /* arm-eabi-gcc -mcpu=cortex-a9 -O3 */
> #include <stdlib.h>
> 
> union  x
> {
>   short a[2];
>   char x[4];
> } __attribute__((packed, aligned(4))) ;
> typedef volatile union  x *s;
> 
> void __attribute__((noinline, noclone))
> check (void)
> {
>   s xx=(s)(0x80000002);
>   /* although volatile xx->x[3] reads 4 bytes here */
>   if (xx->x[3] != 3)
>     abort ();
> }
> 
> void __attribute__((noinline, noclone))
> foo (void)
> {
>   s xx=(s)(0x80000002);
>   xx->x[3] = 3;
> }
> 
> int
> main ()
> {
>   foo ();
>   check ();
>   return 0;
> }

But this testcase is invalid on STRICT_ALIGNMENT platforms: xx is pointer to a 
type with 4-byte alignment so its value must be a multiple of 4.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-08 21:04                                               ` Eric Botcazou
@ 2013-10-08 23:03                                                 ` Bernd Edlinger
  2013-10-11 17:27                                                   ` Eric Botcazou
  2013-10-22 11:02                                                   ` Bernd Edlinger
  0 siblings, 2 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-08 23:03 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener

Hi,

On Tue, 8 Oct 2013 22:50:21, Eric Botcazou wrote:
>
>> I agree, that assigning a non-BLKmode to structures with zero-sized arrays
>> should be considered a bug.
>
> Fine, then let's apply Martin's patch, on mainline at least.
>

That would definitely be a good move. Maybe someone should approve it?

> But this testcase is invalid on STRICT_ALIGNMENT platforms: xx is pointer to a
> type with 4-byte alignment so its value must be a multiple of 4.

Then you probably win. But I still have some doubts.

I had to use this silly alignment/pack(4) to circumvent this statement
in compute_record_mode:

  /* If structure's known alignment is less than what the scalar
     mode would need, and it matters, then stick with BLKmode.  */
  if (TYPE_MODE (type) != BLKmode
      && STRICT_ALIGNMENT
      && ! (TYPE_ALIGN (type)>= BIGGEST_ALIGNMENT
            || TYPE_ALIGN (type)>= GET_MODE_ALIGNMENT (TYPE_MODE (type))))
    {
      /* If this is the only reason this type is BLKmode, then
         don't force containing types to be BLKmode.  */
      TYPE_NO_FORCE_BLK (type) = 1;
      SET_TYPE_MODE (type, BLKmode);
    }

But there are at least two targets where STRICT_ALIGNMENT = 0
and SLOW_UNALIGNED_ACCESS != 0: rs6000 and alpha.

This example with a byte-aligned structure will on one of these targets
likely execute this code path in  expand_expr_real_1/case MEM_REF:

            else if (SLOW_UNALIGNED_ACCESS (mode, align))
              temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
                                        0, TYPE_UNSIGNED (TREE_TYPE (exp)),
                                        (modifier == EXPAND_STACK_PARM
                                         ? NULL_RTX : target),
                                        mode, mode);

This looks wrong, but unfortunately I cannot test on these targets...

Regards
Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-08 23:03                                                 ` Bernd Edlinger
@ 2013-10-11 17:27                                                   ` Eric Botcazou
  2013-10-13  8:22                                                     ` Bernd Edlinger
  2013-10-22 11:02                                                   ` Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-10-11 17:27 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> That would definitely be a good move. Maybe someone should approve it?

Yes, but I agree that we ought to restrict it to trailing zero-sized arrays. 
That would help to allay Jakub's concerns about possible ABI fallouts.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-11 17:27                                                   ` Eric Botcazou
@ 2013-10-13  8:22                                                     ` Bernd Edlinger
  2013-10-13 12:29                                                       ` Eric Botcazou
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-13  8:22 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener

Hi,

>> That would definitely be a good move. Maybe someone should approve it?
>
> Yes, but I agree that we ought to restrict it to trailing zero-sized arrays.
> That would help to allay Jakub's concerns about possible ABI fallouts.
>
> --
> Eric Botcazou

Other uses of zero-sized arrays in structures and unions are
at least questionable, and should be rejected. 

While this construct produces an error:

struct s
{
   int a[];
   float b;
};

error: flexible array member not at end of struct

This does not even produce a waning:

struct s
{
   int a[0];
   float b;
};

Would you agree that this "error: flexible array member"
should also be emitted for a zero-sized array member,
maybe as "error: zero-sized array member not at end of struct"?


Regards
Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-13  8:22                                                     ` Bernd Edlinger
@ 2013-10-13 12:29                                                       ` Eric Botcazou
  2013-10-13 12:30                                                         ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-10-13 12:29 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> Would you agree that this "error: flexible array member"
> should also be emitted for a zero-sized array member,
> maybe as "error: zero-sized array member not at end of struct"?

I would have answered yes when zero-sized arrays where introduced, but it's 
far less clear a couple of decades later IMO.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-13 12:29                                                       ` Eric Botcazou
@ 2013-10-13 12:30                                                         ` Bernd Edlinger
  2013-10-13 14:06                                                           ` Eric Botcazou
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-13 12:30 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 620 bytes --]

Hi Eric,

>> Would you agree that this "error: flexible array member"
>> should also be emitted for a zero-sized array member,
>> maybe as "error: zero-sized array member not at end of struct"?
>
> I would have answered yes when zero-sized arrays where introduced, but it's
> far less clear a couple of decades later IMO.

But if zero-sized arrays everywhere in a structure is valid C,
then the attached test case is a valid test case.
And it will break your patch for PR58570 at -O1 and above,
because you can no longer assume that different array members
are not an alias.


Regards
Bernd. 		 	   		  

[-- Attachment #2: pr58570-1.c --]
[-- Type: text/plain, Size: 268 bytes --]

int printf (const char *, ...);

struct S
{
char a[0];
short b[1];
};

int e = 1, i;
static struct S d;

int
main ()
{
  if (e)
    {
      d.b[i]=!d.b[i]; //0->1
      d.a[i]=!d.a[i]; //1->0
      d.b[i]=!d.b[i]; //0->1
    }
  printf ("%d\n", d.b[0]);
  return 0;
}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-13 12:30                                                         ` Bernd Edlinger
@ 2013-10-13 14:06                                                           ` Eric Botcazou
  0 siblings, 0 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-10-13 14:06 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> But if zero-sized arrays everywhere in a structure is valid C,
> then the attached test case is a valid test case.

Not necessarily, you can write the declaration but you cannot index the array, 
i.e. this is undefined behavior.  And there is nothing new, distinct fields 
have been disambiguated in alias.c for ages.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-08 23:03                                                 ` Bernd Edlinger
  2013-10-11 17:27                                                   ` Eric Botcazou
@ 2013-10-22 11:02                                                   ` Bernd Edlinger
  2013-10-23 16:14                                                     ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-22 11:02 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener

[-- Attachment #1: Type: text/plain, Size: 3080 bytes --]

Hi,

> On Tue, 8 Oct 2013 22:50:21, Eric Botcazou wrote:
>>
>>> I agree, that assigning a non-BLKmode to structures with zero-sized arrays
>>> should be considered a bug.
>>
>> Fine, then let's apply Martin's patch, on mainline at least.
>>
>
> That would definitely be a good move. Maybe someone should approve it?
>
>> But this testcase is invalid on STRICT_ALIGNMENT platforms: xx is pointer to a
>> type with 4-byte alignment so its value must be a multiple of 4.
>
> Then you probably win. But I still have some doubts.
>
> I had to use this silly alignment/pack(4) to circumvent this statement
> in compute_record_mode:
>
>   /* If structure's known alignment is less than what the scalar
>      mode would need, and it matters, then stick with BLKmode.  */
>   if (TYPE_MODE (type) != BLKmode
>       && STRICT_ALIGNMENT
>       && ! (TYPE_ALIGN (type)>= BIGGEST_ALIGNMENT
>             || TYPE_ALIGN (type)>= GET_MODE_ALIGNMENT (TYPE_MODE (type))))
>     {
>       /* If this is the only reason this type is BLKmode, then
>          don't force containing types to be BLKmode.  */
>       TYPE_NO_FORCE_BLK (type) = 1;
>       SET_TYPE_MODE (type, BLKmode);
>     }
>
> But there are at least two targets where STRICT_ALIGNMENT = 0
> and SLOW_UNALIGNED_ACCESS != 0: rs6000 and alpha.
>
> This example with a byte-aligned structure will on one of these targets
> likely execute this code path in  expand_expr_real_1/case MEM_REF:
>
>             else if (SLOW_UNALIGNED_ACCESS (mode, align))
>               temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
>                                         0, TYPE_UNSIGNED (TREE_TYPE (exp)),
>                                         (modifier == EXPAND_STACK_PARM
>                                          ? NULL_RTX : target),
>                                         mode, mode);
>
> This looks wrong, but unfortunately I cannot test on these targets...
>

Hmm, well,

the condition that would be necessary to execute that code path
would be

STRICT_ALIGNMENT = 0
and SLOW_UNALIGNED_ACCESS != 0 for any integer mode.

The only target that is close to hit this "bug" is rs6000:

#define STRICT_ALIGNMENT 0

#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN)                              \
  (STRICT_ALIGNMENT                                                     \
   || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode        \
        || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode)    \
       && (ALIGN) < 32)                                                 \
   || (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE))))

but, luckily this is 0 for all integer modes.

So I am now convinced, there won't be any valid example with unions that
executes this code path.

Therefore I updated Martin's previous patch, to meet Eric's request:
That is to only handle zero-sized arrays at the end of the structure.

Boot-strapped and regression-tested on x86_64-linux-gnu.

Ok for trunk?

Regards
Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748-2.txt --]
[-- Type: text/plain, Size: 351 bytes --]

2013-10-22  Martin Jambor  <mjambor@suse.cz>
	    Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR middle-end/57748
	* stor-layout.c (compute_record_mode): Treat trailing zero-sized array
	fields like incomplete types.

testsuite:
2013-10-22  Bernd Edlinger  <bernd.edlinger@hotmail.de>

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


[-- Attachment #3: patch-pr57748-2.diff --]
[-- Type: application/octet-stream, Size: 1499 bytes --]

--- gcc/stor-layout.c	2013-10-21 08:27:09.546035668 +0200
+++ gcc/stor-layout.c	2013-10-22 10:46:49.233261818 +0200
@@ -1600,7 +1600,10 @@ compute_record_mode (tree type)
 		   && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))))
 	  || ! host_integerp (bit_position (field), 1)
 	  || DECL_SIZE (field) == 0
-	  || ! host_integerp (DECL_SIZE (field), 1))
+	  || ! host_integerp (DECL_SIZE (field), 1)
+	  || (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+	      && tree_low_cst (DECL_SIZE (field), 1) == 0
+	      && simple_cst_equal (TYPE_SIZE (type), bit_position (field))))
 	return;
 
       /* If this field is the whole struct, remember its mode so
--- gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
@@ -0,0 +1,40 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#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 (P *p)
+{
+  if (p->b[0][0] != 3 || p->b[0][1] != 4)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct T *t)
+{
+  V a = { 3, 4 };
+  t->s.b[0] = a;
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+
+  foo (t);
+  check (&t->s);
+
+  free (t);
+  return 0;
+}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-09-17  0:05                   ` Martin Jambor
  2013-09-17 10:32                     ` Bernd Edlinger
@ 2013-10-22 14:08                     ` Bernd Edlinger
  2013-10-23 16:02                       ` Richard Biener
  2013-11-06 15:08                       ` [PATCH, PR 57748] Check for out of bounds access, Part 3 Bernd Edlinger
  1 sibling, 2 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-22 14:08 UTC (permalink / raw)
  To: Martin Jambor; +Cc: Richard Biener, GCC Patches, Eric Botcazou

[-- Attachment #1: Type: text/plain, Size: 1972 bytes --]

Hi, 

On Tue, 17 Sep 2013 01:09:45, Martin Jambor wrote:
>> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
>>        if (MEM_P (to_rtx)
>>            && GET_MODE (to_rtx) == BLKmode
>>            && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
>> +          && bitregion_start == 0
>> +          && bitregion_end == 0
>>            && bitsize> 0
>>            && (bitpos % bitsize) == 0
>>            && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
>>
> ...
>
> I'm not sure to what extent the hunk adding tests for bitregion_start
> and bitregion_end being zero is connected to this issue. I do not see
> any of the testcases exercising that path. If it is indeed another
> problem, I think it should be submitted (and potentially committed) as
> a separate patch, preferably with a testcase.
>

Meanwhile I am able to give an example where that code is executed
with bitpos = 64, bitsize=32, bitregion_start = 32, bitregion_end = 95.

Afterwards bitpos=0, bitsize=32, which is completely outside
bitregion_start=32, bitregion_end=95.

However this can only be seen in the debugger, as the store_field
goes thru a code path that does not look at bitregion_start/end.

Well that is at least extremely ugly, and I would not be sure, that
I cannot come up with a sample that crashes or creates wrong code.

Currently I think that maybe the best way to fix that would be this:

--- gcc/expr.c    2013-10-21 08:27:09.546035668 +0200
+++ gcc/expr.c    2013-10-22 15:19:56.749476525 +0200
@@ -4762,6 +4762,9 @@ expand_assignment (tree to, tree from, b
           && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
         {
           to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
+          bitregion_start = 0;
+          if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos)
+        bitregion_end -= bitpos;
           bitpos = 0;
         }
 
Any suggestions?



Regards
Bernd. 		 	   		  

[-- Attachment #2: t1.c --]
[-- Type: text/plain, Size: 276 bytes --]

extern void abort (void);

struct x{
  int a;
  int :32;
  volatile int b:32;
};

struct s
{
  int a,b,c,d;
  struct x xx[1];
};

struct s ss;
volatile int k;

int main()
{
  ss.xx[k].b = 1;
//  asm volatile("":::"memory");
  if ( ss.xx[k].b != 1)
    abort ();
  return 0;
}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-10-22 14:08                     ` Bernd Edlinger
@ 2013-10-23 16:02                       ` Richard Biener
  2013-10-24  0:09                         ` Bernd Edlinger
  2013-10-24  8:44                         ` Eric Botcazou
  2013-11-06 15:08                       ` [PATCH, PR 57748] Check for out of bounds access, Part 3 Bernd Edlinger
  1 sibling, 2 replies; 105+ messages in thread
From: Richard Biener @ 2013-10-23 16:02 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Martin Jambor, GCC Patches, Eric Botcazou

On Tue, Oct 22, 2013 at 3:50 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi,
>
> On Tue, 17 Sep 2013 01:09:45, Martin Jambor wrote:
>>> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
>>>        if (MEM_P (to_rtx)
>>>            && GET_MODE (to_rtx) == BLKmode
>>>            && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
>>> +          && bitregion_start == 0
>>> +          && bitregion_end == 0
>>>            && bitsize> 0
>>>            && (bitpos % bitsize) == 0
>>>            && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
>>>
>> ...
>>
>> I'm not sure to what extent the hunk adding tests for bitregion_start
>> and bitregion_end being zero is connected to this issue. I do not see
>> any of the testcases exercising that path. If it is indeed another
>> problem, I think it should be submitted (and potentially committed) as
>> a separate patch, preferably with a testcase.
>>
>
> Meanwhile I am able to give an example where that code is executed
> with bitpos = 64, bitsize=32, bitregion_start = 32, bitregion_end = 95.
>
> Afterwards bitpos=0, bitsize=32, which is completely outside
> bitregion_start=32, bitregion_end=95.
>
> However this can only be seen in the debugger, as the store_field
> goes thru a code path that does not look at bitregion_start/end.
>
> Well that is at least extremely ugly, and I would not be sure, that
> I cannot come up with a sample that crashes or creates wrong code.
>
> Currently I think that maybe the best way to fix that would be this:
>
> --- gcc/expr.c    2013-10-21 08:27:09.546035668 +0200
> +++ gcc/expr.c    2013-10-22 15:19:56.749476525 +0200
> @@ -4762,6 +4762,9 @@ expand_assignment (tree to, tree from, b
>            && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
>          {
>            to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
> +          bitregion_start = 0;
> +          if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos)
> +        bitregion_end -= bitpos;
>            bitpos = 0;
>          }
>
> Any suggestions?

if bitregion_start/end are used after the adjust_address call then they have
to be adjusted (or bitpos left in place).  In fact why we apply byte-parts of
bitpos here only if offset != 0 is weird.  OTOH this code is _very_ old...
what happens if you remove the whole case?

Richard.

>
>
> Regards
> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-22 11:02                                                   ` Bernd Edlinger
@ 2013-10-23 16:14                                                     ` Richard Biener
  2013-10-23 17:25                                                       ` Martin Jambor
  2013-10-23 17:45                                                       ` Eric Botcazou
  0 siblings, 2 replies; 105+ messages in thread
From: Richard Biener @ 2013-10-23 16:14 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Eric Botcazou, gcc-patches, Martin Jambor

On Tue, Oct 22, 2013 at 12:25 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi,
>
>> On Tue, 8 Oct 2013 22:50:21, Eric Botcazou wrote:
>>>
>>>> I agree, that assigning a non-BLKmode to structures with zero-sized arrays
>>>> should be considered a bug.
>>>
>>> Fine, then let's apply Martin's patch, on mainline at least.
>>>
>>
>> That would definitely be a good move. Maybe someone should approve it?
>>
>>> But this testcase is invalid on STRICT_ALIGNMENT platforms: xx is pointer to a
>>> type with 4-byte alignment so its value must be a multiple of 4.
>>
>> Then you probably win. But I still have some doubts.
>>
>> I had to use this silly alignment/pack(4) to circumvent this statement
>> in compute_record_mode:
>>
>>   /* If structure's known alignment is less than what the scalar
>>      mode would need, and it matters, then stick with BLKmode.  */
>>   if (TYPE_MODE (type) != BLKmode
>>       && STRICT_ALIGNMENT
>>       && ! (TYPE_ALIGN (type)>= BIGGEST_ALIGNMENT
>>             || TYPE_ALIGN (type)>= GET_MODE_ALIGNMENT (TYPE_MODE (type))))
>>     {
>>       /* If this is the only reason this type is BLKmode, then
>>          don't force containing types to be BLKmode.  */
>>       TYPE_NO_FORCE_BLK (type) = 1;
>>       SET_TYPE_MODE (type, BLKmode);
>>     }
>>
>> But there are at least two targets where STRICT_ALIGNMENT = 0
>> and SLOW_UNALIGNED_ACCESS != 0: rs6000 and alpha.
>>
>> This example with a byte-aligned structure will on one of these targets
>> likely execute this code path in  expand_expr_real_1/case MEM_REF:
>>
>>             else if (SLOW_UNALIGNED_ACCESS (mode, align))
>>               temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
>>                                         0, TYPE_UNSIGNED (TREE_TYPE (exp)),
>>                                         (modifier == EXPAND_STACK_PARM
>>                                          ? NULL_RTX : target),
>>                                         mode, mode);
>>
>> This looks wrong, but unfortunately I cannot test on these targets...
>>
>
> Hmm, well,
>
> the condition that would be necessary to execute that code path
> would be
>
> STRICT_ALIGNMENT = 0
> and SLOW_UNALIGNED_ACCESS != 0 for any integer mode.
>
> The only target that is close to hit this "bug" is rs6000:
>
> #define STRICT_ALIGNMENT 0
>
> #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN)                              \
>   (STRICT_ALIGNMENT                                                     \
>    || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode        \
>         || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode)    \
>        && (ALIGN) < 32)                                                 \
>    || (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE))))
>
> but, luckily this is 0 for all integer modes.
>
> So I am now convinced, there won't be any valid example with unions that
> executes this code path.
>
> Therefore I updated Martin's previous patch, to meet Eric's request:
> That is to only handle zero-sized arrays at the end of the structure.

That looks backwards.  Why should

struct { V i; V j[0]; }

have a different mode than

struct { V j[0]; V i; }

?  And why should the same issue not exist for

struct { V a[1]; }

which is also "flexible enough" that we support accesses beyond it
via a pointer?  That struct also has V2DImode.  And this is all
because

      /* If this field is the whole struct, remember its mode so
         that, say, we can put a double in a class into a DF
         register instead of forcing it to live in the stack.  */
      if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
        mode = DECL_MODE (field);

which is IMHO ok.

> Boot-strapped and regression-tested on x86_64-linux-gnu.
>
> Ok for trunk?

Well, I'm not so sure.  And if so then I'd prefer martins original
patch, rejecting all zero-sized fields.  But then only if you
consider it a "real" field.

Of course I blame those that added the zero-sized array extension
for all this mess ... maybe we can reduce it by rejecting
zero-sized arrays that are not at the end of a structure - which means
we can demote them to flexible arrays with a NULL TYPE_SIZE
which would completely side-step this issue in stor-layout.c.

Richard.

> Regards
> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-23 16:14                                                     ` Richard Biener
@ 2013-10-23 17:25                                                       ` Martin Jambor
  2013-10-23 18:05                                                         ` Eric Botcazou
  2013-10-24  8:20                                                         ` Bernd Edlinger
  2013-10-23 17:45                                                       ` Eric Botcazou
  1 sibling, 2 replies; 105+ messages in thread
From: Martin Jambor @ 2013-10-23 17:25 UTC (permalink / raw)
  To: Richard Biener; +Cc: Bernd Edlinger, Eric Botcazou, gcc-patches

Hi,

On Wed, Oct 23, 2013 at 06:00:43PM +0200, Richard Biener wrote:
>

...

> ?  And why should the same issue not exist for
> 
> struct { V a[1]; }
> 

indeed, it does and it's simple to trigger (on x86_64):

----------------------------------------
/* { dg-do run } */

#include <stdlib.h>

typedef long long V
  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));

#if 1
typedef struct S {V b[1]; } P __attribute__((aligned (1)));
struct __attribute__((packed)) T { char c; P s; };
#else
typedef struct S {V b[1]; } P;
struct T { char c; P s; };
#endif

void __attribute__((noinline, noclone))
good_value (V b)
{
  if (b[0] != 3 || b[1] != 4)
    __builtin_abort ();
}

void __attribute__((noinline, noclone))
check (P *p)
{
  good_value (p->b[1]);
}

int
main ()
{
  struct T *t = (struct T *) calloc (128, 1);
  V a = { 3, 4 };
  t->s.b[1] = a;
  check (&t->s);
  free (t);
  return 0;
}
----------------------------------------

While I was willing to discount the zero sized array as an
insufficiently specified oddity, this seems to be much more serious
and potentially common.  It seems we really need to be able to detect
these out-of-bounds situations and tell lower levels of expander that
"whatever mode you think you are expanding, it is actually BLK mode."

It's uglier than I thought.

Martin


> which is also "flexible enough" that we support accesses beyond it
> via a pointer?  That struct also has V2DImode.  And this is all
> because
> 
>       /* If this field is the whole struct, remember its mode so
>          that, say, we can put a double in a class into a DF
>          register instead of forcing it to live in the stack.  */
>       if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
>         mode = DECL_MODE (field);
> 
> which is IMHO ok.
> 
> > Boot-strapped and regression-tested on x86_64-linux-gnu.
> >
> > Ok for trunk?
> 
> Well, I'm not so sure.  And if so then I'd prefer martins original
> patch, rejecting all zero-sized fields.  But then only if you
> consider it a "real" field.
> 
> Of course I blame those that added the zero-sized array extension
> for all this mess ... maybe we can reduce it by rejecting
> zero-sized arrays that are not at the end of a structure - which means
> we can demote them to flexible arrays with a NULL TYPE_SIZE
> which would completely side-step this issue in stor-layout.c.
> 
> Richard.
> 
> > Regards
> > Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-23 16:14                                                     ` Richard Biener
  2013-10-23 17:25                                                       ` Martin Jambor
@ 2013-10-23 17:45                                                       ` Eric Botcazou
  1 sibling, 0 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-10-23 17:45 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor

> That looks backwards.  Why should
> 
> struct { V i; V j[0]; }
> 
> have a different mode than
> 
> struct { V j[0]; V i; }
> 
> ?

Because we support out-of-bounds access for the array in the former case and 
not in the latter case.

> And why should the same issue not exist for
> 
> struct { V a[1]; }
> 
> which is also "flexible enough" that we support accesses beyond it
> via a pointer?  That struct also has V2DImode.  And this is all
> because
> 
>       /* If this field is the whole struct, remember its mode so
>          that, say, we can put a double in a class into a DF
>          register instead of forcing it to live in the stack.  */
>       if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
>         mode = DECL_MODE (field);
> 
> which is IMHO ok.

It's OK *only* if TYPE_SIZE (type) is really the size of all the objects of 
the type; if it isn't, i.e. if we allow access past TYPE_SIZE (type), then we 
cannot use the field's mode.  So we need to decide where to draw the line.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-23 17:25                                                       ` Martin Jambor
@ 2013-10-23 18:05                                                         ` Eric Botcazou
  2013-10-24  8:20                                                         ` Bernd Edlinger
  1 sibling, 0 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-10-23 18:05 UTC (permalink / raw)
  To: Martin Jambor; +Cc: gcc-patches, Richard Biener, Bernd Edlinger

> While I was willing to discount the zero sized array as an
> insufficiently specified oddity, this seems to be much more serious
> and potentially common.  It seems we really need to be able to detect
> these out-of-bounds situations and tell lower levels of expander that
> "whatever mode you think you are expanding, it is actually BLK mode."

Please let's not enter this hazardous business.  We just need to draw a line 
somewhere and clearly state what we support in terms of out-of-bounds access.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-10-23 16:02                       ` Richard Biener
@ 2013-10-24  0:09                         ` Bernd Edlinger
  2013-10-24  8:44                         ` Eric Botcazou
  1 sibling, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-24  0:09 UTC (permalink / raw)
  To: Richard Biener; +Cc: Martin Jambor, GCC Patches, Eric Botcazou

[-- Attachment #1: Type: text/plain, Size: 1106 bytes --]

On, Wed, 23 Oct 2013 17:36:41Richard Biener wrote:
>
> if bitregion_start/end are used after the adjust_address call then they have
> to be adjusted (or bitpos left in place). In fact why we apply byte-parts of
> bitpos here only if offset != 0 is weird. OTOH this code is _very_ old...
> what happens if you remove the whole case?
>
> Richard.
>

If I remove that code completely...

Than changes nothing ARM at -O2.
and on x86 at -O2 this changes:

        .cfi_startproc
        movl    k, %eax
        leal    (%eax,%eax,2), %eax
-       leal    ss+8(,%eax,4), %eax
-       movl    $1, 16(%eax)
+       leal    ss+16(,%eax,4), %eax
+       movl    $1, 8(%eax)
        movl    k, %eax
        leal    (%eax,%eax,2), %eax
-       leal    ss+8(,%eax,4), %eax
-       movl    16(%eax), %eax
+       leal    ss+16(,%eax,4), %eax
+       movl    8(%eax), %eax
        cmpl    $1, %eax
        jne     .L5
        xorl    %eax, %eax


that does not really make any difference.

So removing that code looks like a nice alternative.

What do you think?

Bernd. 		 	   		  

[-- Attachment #2: patch-pr57748-3.diff --]
[-- Type: application/octet-stream, Size: 1607 bytes --]

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 203898)
+++ gcc/expr.c	(working copy)
@@ -4752,20 +4752,6 @@
 	  if (GET_MODE (offset_rtx) != address_mode)
 	    offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
-	  /* A constant address in TO_RTX can have VOIDmode, we must not try
-	     to call force_reg for that case.  Avoid that case.  */
-	  if (MEM_P (to_rtx)
-	      && GET_MODE (to_rtx) == BLKmode
-	      && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
-	      && bitsize > 0
-	      && (bitpos % bitsize) == 0
-	      && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
-	      && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
-	    {
-	      to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
-	      bitpos = 0;
-	    }
-
 	  to_rtx = offset_address (to_rtx, offset_rtx,
 				   highest_pow2_factor_for_target (to,
 				   				   offset));
@@ -9981,19 +9967,6 @@
 	    if (GET_MODE (offset_rtx) != address_mode)
 	      offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
-	    if (GET_MODE (op0) == BLKmode
-		/* A constant address in OP0 can have VOIDmode, we must
-		   not try to call force_reg in that case.  */
-		&& GET_MODE (XEXP (op0, 0)) != VOIDmode
-		&& bitsize != 0
-		&& (bitpos % bitsize) == 0
-		&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
-		&& MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
-	      {
-		op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
-		bitpos = 0;
-	      }
-
 	    op0 = offset_address (op0, offset_rtx,
 				  highest_pow2_factor (offset));
 	  }

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-23 17:25                                                       ` Martin Jambor
  2013-10-23 18:05                                                         ` Eric Botcazou
@ 2013-10-24  8:20                                                         ` Bernd Edlinger
  2013-10-24  9:16                                                           ` Eric Botcazou
  2013-10-24 11:14                                                           ` Richard Biener
  1 sibling, 2 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-24  8:20 UTC (permalink / raw)
  To: Martin Jambor, Richard Biener; +Cc: Eric Botcazou, gcc-patches

Hi Martin,

On Wed, 23 Oct 2013 19:11:06, Martin Jambor wrote:
> On Wed, Oct 23, 2013 at 06:00:43PM +0200, Richard Biener wrote:
>>
>
> ...
>
>> ? And why should the same issue not exist for
>>
>> struct { V a[1]; }
>>
>
> indeed, it does and it's simple to trigger (on x86_64):
>
> ----------------------------------------
> /* { dg-do run } */
>
> #include <stdlib.h>
>
> typedef long long V
> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
>
> #if 1
> typedef struct S {V b[1]; } P __attribute__((aligned (1)));
> struct __attribute__((packed)) T { char c; P s; };
> #else
> typedef struct S {V b[1]; } P;
> struct T { char c; P s; };
> #endif
>
> void __attribute__((noinline, noclone))
> good_value (V b)
> {
> if (b[0] != 3 || b[1] != 4)
> __builtin_abort ();
> }
>
> void __attribute__((noinline, noclone))
> check (P *p)
> {
> good_value (p->b[1]);
> }
>
> int
> main ()
> {
> struct T *t = (struct T *) calloc (128, 1);
> V a = { 3, 4 };
> t->s.b[1] = a;
> check (&t->s);
> free (t);
> return 0;
> }
> ----------------------------------------
>
> While I was willing to discount the zero sized array as an
> insufficiently specified oddity, this seems to be much more serious
> and potentially common. It seems we really need to be able to detect
> these out-of-bounds situations and tell lower levels of expander that
> "whatever mode you think you are expanding, it is actually BLK mode."
>
> It's uglier than I thought.
>
> Martin
>

Deja-vu...

Thanks for this test case. This definitely destroys the idea to fix this in stor-layout.c

I think that is common practice to write array[1]; at the end of the structure,
and use it as a flexible array. The compute_record_mode has no way to
decide if that is going to be a flexible array or not.

Sorry Eric, but now I have no other choice than to go back to my previous version
of part 2:

http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html

I'd just add Martin's new test case as 57748-4.c.


Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-10-23 16:02                       ` Richard Biener
  2013-10-24  0:09                         ` Bernd Edlinger
@ 2013-10-24  8:44                         ` Eric Botcazou
  2013-10-24 10:06                           ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-10-24  8:44 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor

> if bitregion_start/end are used after the adjust_address call then they have
> to be adjusted (or bitpos left in place).  In fact why we apply byte-parts
> of bitpos here only if offset != 0 is weird.

Presumably to be able to do arithmetic on symbols when the offset is variable, 
which can save one addition in the final code.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24  8:20                                                         ` Bernd Edlinger
@ 2013-10-24  9:16                                                           ` Eric Botcazou
  2013-10-24 10:00                                                             ` Bernd Edlinger
  2013-10-24 10:50                                                             ` Richard Biener
  2013-10-24 11:14                                                           ` Richard Biener
  1 sibling, 2 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-10-24  9:16 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> I think that is common practice to write array[1]; at the end of the
> structure, and use it as a flexible array. The compute_record_mode has no
> way to decide if that is going to be a flexible array or not.
> 
> Sorry Eric, but now I have no other choice than to go back to my previous
> version of part 2:
> 
> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html

Why?  Just set BLKmode in this case as well.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24  9:16                                                           ` Eric Botcazou
@ 2013-10-24 10:00                                                             ` Bernd Edlinger
  2013-10-24 10:16                                                               ` Eric Botcazou
  2013-10-24 10:50                                                             ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-24 10:00 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Martin Jambor, Richard Biener

>> I think that is common practice to write array[1]; at the end of the
>> structure, and use it as a flexible array. The compute_record_mode has no
>> way to decide if that is going to be a flexible array or not.
>>
>> Sorry Eric, but now I have no other choice than to go back to my previous
>> version of part 2:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html
>
> Why? Just set BLKmode in this case as well.

Because of the ABI-change?

>
> --
> Eric Botcazou 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-10-24  8:44                         ` Eric Botcazou
@ 2013-10-24 10:06                           ` Richard Biener
  2013-10-24 10:22                             ` Bernd Edlinger
  2013-10-25 10:40                             ` Eric Botcazou
  0 siblings, 2 replies; 105+ messages in thread
From: Richard Biener @ 2013-10-24 10:06 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: GCC Patches, Bernd Edlinger, Martin Jambor

On Thu, Oct 24, 2013 at 10:37 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> if bitregion_start/end are used after the adjust_address call then they have
>> to be adjusted (or bitpos left in place).  In fact why we apply byte-parts
>> of bitpos here only if offset != 0 is weird.
>
> Presumably to be able to do arithmetic on symbols when the offset is variable,
> which can save one addition in the final code.

Doesn't that also apply to arithmetic on symbols when the offset is NULL?
But yes, the codegen example posted shows this kind of difference
(though it doesn't seem to save anything for that case).  I'd have expected
a more explicit guarding of this case, like with MEM_P (to_rtx)
&& SYMBOL_REF_P (XEXP (to_rtx, 0)) though, eventually even looking
whether the resulting address is legitimate.  But ... doesn't forwprop
fix this up later anyway?

Either way, bitregion_start/end is clearly wrong after we hit this case.
I'm always fast approving removal of "odd" code (less-code-is-better
doctrine...), but in this case maybe the code can be improved instead.
The comment before it is also odd and likely only applies to later
added restrictions.  Just to quote it again:

   if (offset != 0)
     {
...
          /* A constant address in TO_RTX can have VOIDmode, we must not try
             to call force_reg for that case.  Avoid that case.  */
          if (MEM_P (to_rtx)
              && GET_MODE (to_rtx) == BLKmode
              && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
              && bitsize > 0
              && (bitpos % bitsize) == 0
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
              && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
            {
              to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
              bitpos = 0;
            }

          to_rtx = offset_address (to_rtx, offset_rtx,
                                   highest_pow2_factor_for_target (to,
                                                                   offset));
        }


Thanks,
Richard.

> --
> Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24 10:00                                                             ` Bernd Edlinger
@ 2013-10-24 10:16                                                               ` Eric Botcazou
  0 siblings, 0 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-10-24 10:16 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Martin Jambor, Richard Biener

> Because of the ABI-change?

While concerns about accidental ABI changes are real, they shouldn't be 
overstated either.  We have been saying for longer than a decade that the 
back-ends must not use the type mode to implement calling conventions and 
other external interfaces.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access
  2013-10-24 10:06                           ` Richard Biener
@ 2013-10-24 10:22                             ` Bernd Edlinger
  2013-10-25 10:40                             ` Eric Botcazou
  1 sibling, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-24 10:22 UTC (permalink / raw)
  To: Richard Biener, Eric Botcazou; +Cc: GCC Patches, Martin Jambor

Hi,

On Thu, 24 Oct 2013 11:56:52, Richard Biener wrote:
>
> On Thu, Oct 24, 2013 at 10:37 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>>> if bitregion_start/end are used after the adjust_address call then they have
>>> to be adjusted (or bitpos left in place). In fact why we apply byte-parts
>>> of bitpos here only if offset != 0 is weird.
>>
>> Presumably to be able to do arithmetic on symbols when the offset is variable,
>> which can save one addition in the final code.
>
> Doesn't that also apply to arithmetic on symbols when the offset is NULL?
> But yes, the codegen example posted shows this kind of difference
> (though it doesn't seem to save anything for that case). I'd have expected
> a more explicit guarding of this case, like with MEM_P (to_rtx)
> && SYMBOL_REF_P (XEXP (to_rtx, 0)) though, eventually even looking
> whether the resulting address is legitimate. But ... doesn't forwprop
> fix this up later anyway?
>
> Either way, bitregion_start/end is clearly wrong after we hit this case.
> I'm always fast approving removal of "odd" code (less-code-is-better
> doctrine...), but in this case maybe the code can be improved instead.
> The comment before it is also odd and likely only applies to later
> added restrictions. Just to quote it again:
>
> if (offset != 0)
> {
> ...
> /* A constant address in TO_RTX can have VOIDmode, we must not try
> to call force_reg for that case. Avoid that case. */
> if (MEM_P (to_rtx)
> && GET_MODE (to_rtx) == BLKmode
> && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
> && bitsize> 0
> && (bitpos % bitsize) == 0
> && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
> && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
> {
> to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
> bitpos = 0;
> }
>
> to_rtx = offset_address (to_rtx, offset_rtx,
> highest_pow2_factor_for_target (to,
> offset));
> }
>

In the initial commit from 1998 where this was introduced that
block contained an explicit force_reg call, but not that comment.

Bernd.
>
> Thanks,
> Richard.
>
>> --
>> Eric Botcazou 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24  9:16                                                           ` Eric Botcazou
  2013-10-24 10:00                                                             ` Bernd Edlinger
@ 2013-10-24 10:50                                                             ` Richard Biener
  2013-10-24 13:09                                                               ` Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Richard Biener @ 2013-10-24 10:50 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: Bernd Edlinger, GCC Patches, Martin Jambor

On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> I think that is common practice to write array[1]; at the end of the
>> structure, and use it as a flexible array. The compute_record_mode has no
>> way to decide if that is going to be a flexible array or not.
>>
>> Sorry Eric, but now I have no other choice than to go back to my previous
>> version of part 2:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html
>
> Why?  Just set BLKmode in this case as well.

Works for me if it works ABI-wise (which you say it should unless the
backend is buggy).  Note that means mode_for_array should unconditionally
return BLKmode.

Richard.

> --
> Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24  8:20                                                         ` Bernd Edlinger
  2013-10-24  9:16                                                           ` Eric Botcazou
@ 2013-10-24 11:14                                                           ` Richard Biener
  2013-10-24 13:13                                                             ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Richard Biener @ 2013-10-24 11:14 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Martin Jambor, Eric Botcazou, gcc-patches

On Thu, Oct 24, 2013 at 9:15 AM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi Martin,
>
> On Wed, 23 Oct 2013 19:11:06, Martin Jambor wrote:
>> On Wed, Oct 23, 2013 at 06:00:43PM +0200, Richard Biener wrote:
>>>
>>
>> ...
>>
>>> ? And why should the same issue not exist for
>>>
>>> struct { V a[1]; }
>>>
>>
>> indeed, it does and it's simple to trigger (on x86_64):
>>
>> ----------------------------------------
>> /* { dg-do run } */
>>
>> #include <stdlib.h>
>>
>> typedef long long V
>> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
>>
>> #if 1
>> typedef struct S {V b[1]; } P __attribute__((aligned (1)));
>> struct __attribute__((packed)) T { char c; P s; };
>> #else
>> typedef struct S {V b[1]; } P;
>> struct T { char c; P s; };
>> #endif
>>
>> void __attribute__((noinline, noclone))
>> good_value (V b)
>> {
>> if (b[0] != 3 || b[1] != 4)
>> __builtin_abort ();
>> }
>>
>> void __attribute__((noinline, noclone))
>> check (P *p)
>> {
>> good_value (p->b[1]);
>> }
>>
>> int
>> main ()
>> {
>> struct T *t = (struct T *) calloc (128, 1);
>> V a = { 3, 4 };
>> t->s.b[1] = a;
>> check (&t->s);
>> free (t);
>> return 0;
>> }
>> ----------------------------------------
>>
>> While I was willing to discount the zero sized array as an
>> insufficiently specified oddity, this seems to be much more serious
>> and potentially common. It seems we really need to be able to detect
>> these out-of-bounds situations and tell lower levels of expander that
>> "whatever mode you think you are expanding, it is actually BLK mode."
>>
>> It's uglier than I thought.
>>
>> Martin
>>
>
> Deja-vu...
>
> Thanks for this test case. This definitely destroys the idea to fix this in stor-layout.c
>
> I think that is common practice to write array[1]; at the end of the structure,
> and use it as a flexible array.

Same for stuff like

 struct X { char c[4]; };

that currently gets SImode.  In alias handling we treat all trailing
arrays as flexible, even if they happen to be nested in sub-structs like for

 struct X { int i; struct Y { char c[4]; } };

too much code out in the wild to disallow this.

> The compute_record_mode has no way to
> decide if that is going to be a flexible array or not.

But it could assign BLKmode to _all_ array types.

Richard.

> Sorry Eric, but now I have no other choice than to go back to my previous version
> of part 2:
>
> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html
>
> I'd just add Martin's new test case as 57748-4.c.
>
>
> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24 10:50                                                             ` Richard Biener
@ 2013-10-24 13:09                                                               ` Bernd Edlinger
  2013-10-24 13:16                                                                 ` Richard Biener
  2013-10-24 13:20                                                                 ` Jakub Jelinek
  0 siblings, 2 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-24 13:09 UTC (permalink / raw)
  To: Richard Biener, Eric Botcazou; +Cc: GCC Patches, Martin Jambor

On Thu, 24 Oct 2013 12:18:43, Richard Biener wrote:
>
> On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>>> I think that is common practice to write array[1]; at the end of the
>>> structure, and use it as a flexible array. The compute_record_mode has no
>>> way to decide if that is going to be a flexible array or not.
>>>
>>> Sorry Eric, but now I have no other choice than to go back to my previous
>>> version of part 2:
>>>
>>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html
>>
>> Why? Just set BLKmode in this case as well.
>
> Works for me if it works ABI-wise (which you say it should unless the
> backend is buggy). Note that means mode_for_array should unconditionally
> return BLKmode.

Did you just propose:

--- stor-layout.c.orig    2013-10-22 10:46:49.233261818 +0200
+++ stor-layout.c    2013-10-24 14:54:00.425259062 +0200
@@ -471,27 +471,7 @@
 static enum machine_mode
 mode_for_array (tree elem_type, tree size)
 {
-  tree elem_size;
-  unsigned HOST_WIDE_INT int_size, int_elem_size;
-  bool limit_p;
-
-  /* One-element arrays get the component type's mode.  */
-  elem_size = TYPE_SIZE (elem_type);
-  if (simple_cst_equal (size, elem_size))
-    return TYPE_MODE (elem_type);
-
-  limit_p = true;
-  if (host_integerp (size, 1) && host_integerp (elem_size, 1))
-    {
-      int_size = tree_low_cst (size, 1);
-      int_elem_size = tree_low_cst (elem_size, 1);
-      if (int_elem_size> 0
-      && int_size % int_elem_size == 0
-      && targetm.array_mode_supported_p (TYPE_MODE (elem_type),
-                         int_size / int_elem_size))
-    limit_p = false;
-    }
-  return mode_for_size_tree (size, MODE_INT, limit_p);
+  return BLKmode;
 }

???


> Richard.
>
>> --
>> Eric Botcazou 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24 11:14                                                           ` Richard Biener
@ 2013-10-24 13:13                                                             ` Richard Biener
  0 siblings, 0 replies; 105+ messages in thread
From: Richard Biener @ 2013-10-24 13:13 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Martin Jambor, Eric Botcazou, gcc-patches

On Thu, Oct 24, 2013 at 12:22 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Thu, Oct 24, 2013 at 9:15 AM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
>> Hi Martin,
>>
>> On Wed, 23 Oct 2013 19:11:06, Martin Jambor wrote:
>>> On Wed, Oct 23, 2013 at 06:00:43PM +0200, Richard Biener wrote:
>>>>
>>>
>>> ...
>>>
>>>> ? And why should the same issue not exist for
>>>>
>>>> struct { V a[1]; }
>>>>
>>>
>>> indeed, it does and it's simple to trigger (on x86_64):
>>>
>>> ----------------------------------------
>>> /* { dg-do run } */
>>>
>>> #include <stdlib.h>
>>>
>>> typedef long long V
>>> __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
>>>
>>> #if 1
>>> typedef struct S {V b[1]; } P __attribute__((aligned (1)));
>>> struct __attribute__((packed)) T { char c; P s; };
>>> #else
>>> typedef struct S {V b[1]; } P;
>>> struct T { char c; P s; };
>>> #endif
>>>
>>> void __attribute__((noinline, noclone))
>>> good_value (V b)
>>> {
>>> if (b[0] != 3 || b[1] != 4)
>>> __builtin_abort ();
>>> }
>>>
>>> void __attribute__((noinline, noclone))
>>> check (P *p)
>>> {
>>> good_value (p->b[1]);
>>> }
>>>
>>> int
>>> main ()
>>> {
>>> struct T *t = (struct T *) calloc (128, 1);
>>> V a = { 3, 4 };
>>> t->s.b[1] = a;
>>> check (&t->s);
>>> free (t);
>>> return 0;
>>> }
>>> ----------------------------------------
>>>
>>> While I was willing to discount the zero sized array as an
>>> insufficiently specified oddity, this seems to be much more serious
>>> and potentially common. It seems we really need to be able to detect
>>> these out-of-bounds situations and tell lower levels of expander that
>>> "whatever mode you think you are expanding, it is actually BLK mode."
>>>
>>> It's uglier than I thought.
>>>
>>> Martin
>>>
>>
>> Deja-vu...
>>
>> Thanks for this test case. This definitely destroys the idea to fix this in stor-layout.c
>>
>> I think that is common practice to write array[1]; at the end of the structure,
>> and use it as a flexible array.
>
> Same for stuff like
>
>  struct X { char c[4]; };
>
> that currently gets SImode.  In alias handling we treat all trailing
> arrays as flexible, even if they happen to be nested in sub-structs like for
>
>  struct X { int i; struct Y { char c[4]; } };
>
> too much code out in the wild to disallow this.
>
>> The compute_record_mode has no way to
>> decide if that is going to be a flexible array or not.
>
> But it could assign BLKmode to _all_ array types.

And if it is to prevent ICEs then even struct Y { char c[1]; char c2; }
which gets HImode might be used as ((struct Y *)p)->c[1] - invalid
but still shouldn't ICE in any way.

Richard.

> Richard.
>
>> Sorry Eric, but now I have no other choice than to go back to my previous version
>> of part 2:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html
>>
>> I'd just add Martin's new test case as 57748-4.c.
>>
>>
>> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24 13:09                                                               ` Bernd Edlinger
@ 2013-10-24 13:16                                                                 ` Richard Biener
  2013-10-24 13:38                                                                   ` Bernd Edlinger
  2013-10-25  7:05                                                                   ` Bernd Edlinger
  2013-10-24 13:20                                                                 ` Jakub Jelinek
  1 sibling, 2 replies; 105+ messages in thread
From: Richard Biener @ 2013-10-24 13:16 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor

On Thu, Oct 24, 2013 at 2:55 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> On Thu, 24 Oct 2013 12:18:43, Richard Biener wrote:
>>
>> On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>>>> I think that is common practice to write array[1]; at the end of the
>>>> structure, and use it as a flexible array. The compute_record_mode has no
>>>> way to decide if that is going to be a flexible array or not.
>>>>
>>>> Sorry Eric, but now I have no other choice than to go back to my previous
>>>> version of part 2:
>>>>
>>>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html
>>>
>>> Why? Just set BLKmode in this case as well.
>>
>> Works for me if it works ABI-wise (which you say it should unless the
>> backend is buggy). Note that means mode_for_array should unconditionally
>> return BLKmode.
>
> Did you just propose:
>
> --- stor-layout.c.orig    2013-10-22 10:46:49.233261818 +0200
> +++ stor-layout.c    2013-10-24 14:54:00.425259062 +0200
> @@ -471,27 +471,7 @@
>  static enum machine_mode
>  mode_for_array (tree elem_type, tree size)
>  {
> -  tree elem_size;
> -  unsigned HOST_WIDE_INT int_size, int_elem_size;
> -  bool limit_p;
> -
> -  /* One-element arrays get the component type's mode.  */
> -  elem_size = TYPE_SIZE (elem_type);
> -  if (simple_cst_equal (size, elem_size))
> -    return TYPE_MODE (elem_type);
> -
> -  limit_p = true;
> -  if (host_integerp (size, 1) && host_integerp (elem_size, 1))
> -    {
> -      int_size = tree_low_cst (size, 1);
> -      int_elem_size = tree_low_cst (elem_size, 1);
> -      if (int_elem_size> 0
> -      && int_size % int_elem_size == 0
> -      && targetm.array_mode_supported_p (TYPE_MODE (elem_type),
> -                         int_size / int_elem_size))
> -    limit_p = false;
> -    }
> -  return mode_for_size_tree (size, MODE_INT, limit_p);
> +  return BLKmode;
>  }
>
> ???

Yes.  Does it work?

Richard.

>
>> Richard.
>>
>>> --
>>> Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24 13:09                                                               ` Bernd Edlinger
  2013-10-24 13:16                                                                 ` Richard Biener
@ 2013-10-24 13:20                                                                 ` Jakub Jelinek
  2013-10-24 13:42                                                                   ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Jakub Jelinek @ 2013-10-24 13:20 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Richard Biener, Eric Botcazou, GCC Patches, Martin Jambor

On Thu, Oct 24, 2013 at 02:55:59PM +0200, Bernd Edlinger wrote:
> On Thu, 24 Oct 2013 12:18:43, Richard Biener wrote:
> >
> > On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> >>> I think that is common practice to write array[1]; at the end of the
> >>> structure, and use it as a flexible array. The compute_record_mode has no
> >>> way to decide if that is going to be a flexible array or not.
> >>>
> >>> Sorry Eric, but now I have no other choice than to go back to my previous
> >>> version of part 2:
> >>>
> >>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html
> >>
> >> Why? Just set BLKmode in this case as well.
> >
> > Works for me if it works ABI-wise (which you say it should unless the
> > backend is buggy). Note that means mode_for_array should unconditionally
> > return BLKmode.
> 
> Did you just propose:

But why would we want to penalize the generated code for this?
I mean, if some structure has a flexible array member or something similar
to it that we allow to be used as one, if we pass it as arguments, return
from functions etc., it will not have any bits beyond those and thus it
should be just fine to be passed in registers etc.  We can only use those
extra bits if either we allocate them on the heap/stack (malloc, alloca,
...) or as a global or automatic variable with initializer that fills in the
zero sized array or flexible array member (GNU extensions?), but in either
of these cases the DECL_MODE or TYPE_MODE should be irrelevant.

So to me this really sounds like a bug in the expansion, certainly not
stor-layout.

	Jakub

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24 13:16                                                                 ` Richard Biener
@ 2013-10-24 13:38                                                                   ` Bernd Edlinger
  2013-10-25  7:05                                                                   ` Bernd Edlinger
  1 sibling, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-24 13:38 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

>> Did you just propose:
>>
>> --- stor-layout.c.orig 2013-10-22 10:46:49.233261818 +0200
>> +++ stor-layout.c 2013-10-24 14:54:00.425259062 +0200
>> @@ -471,27 +471,7 @@
>> static enum machine_mode
>> mode_for_array (tree elem_type, tree size)
>> {
>> - tree elem_size;
>> - unsigned HOST_WIDE_INT int_size, int_elem_size;
>> - bool limit_p;
>> -
>> - /* One-element arrays get the component type's mode. */
>> - elem_size = TYPE_SIZE (elem_type);
>> - if (simple_cst_equal (size, elem_size))
>> - return TYPE_MODE (elem_type);
>> -
>> - limit_p = true;
>> - if (host_integerp (size, 1) && host_integerp (elem_size, 1))
>> - {
>> - int_size = tree_low_cst (size, 1);
>> - int_elem_size = tree_low_cst (elem_size, 1);
>> - if (int_elem_size> 0
>> - && int_size % int_elem_size == 0
>> - && targetm.array_mode_supported_p (TYPE_MODE (elem_type),
>> - int_size / int_elem_size))
>> - limit_p = false;
>> - }
>> - return mode_for_size_tree (size, MODE_INT, limit_p);
>> + return BLKmode;
>> }
>>
>> ???
>
> Yes. Does it work?
>
> Richard.
>

I will give it a try.

I could also explicitly catch the case "struct { a[x]; };"
in compute_record_mode. That might work too.
But one way or the other that fix will be ugly.

Note:
struct Y { char c[1]; char c2; };

is "invalid" even if the expander would not fail,
because the code in tree-ssa-alias.c will not see the alias,
between c[2] and c2, that works only for the last array.
So that is no ICE but all generated code at -O1 and higher
will be wrong.

Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24 13:20                                                                 ` Jakub Jelinek
@ 2013-10-24 13:42                                                                   ` Richard Biener
  0 siblings, 0 replies; 105+ messages in thread
From: Richard Biener @ 2013-10-24 13:42 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Bernd Edlinger, Eric Botcazou, GCC Patches, Martin Jambor

On Thu, Oct 24, 2013 at 3:13 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Thu, Oct 24, 2013 at 02:55:59PM +0200, Bernd Edlinger wrote:
>> On Thu, 24 Oct 2013 12:18:43, Richard Biener wrote:
>> >
>> > On Thu, Oct 24, 2013 at 10:48 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> >>> I think that is common practice to write array[1]; at the end of the
>> >>> structure, and use it as a flexible array. The compute_record_mode has no
>> >>> way to decide if that is going to be a flexible array or not.
>> >>>
>> >>> Sorry Eric, but now I have no other choice than to go back to my previous
>> >>> version of part 2:
>> >>>
>> >>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00222.html
>> >>
>> >> Why? Just set BLKmode in this case as well.
>> >
>> > Works for me if it works ABI-wise (which you say it should unless the
>> > backend is buggy). Note that means mode_for_array should unconditionally
>> > return BLKmode.
>>
>> Did you just propose:
>
> But why would we want to penalize the generated code for this?
> I mean, if some structure has a flexible array member or something similar
> to it that we allow to be used as one, if we pass it as arguments, return
> from functions etc., it will not have any bits beyond those and thus it
> should be just fine to be passed in registers etc.  We can only use those
> extra bits if either we allocate them on the heap/stack (malloc, alloca,
> ...) or as a global or automatic variable with initializer that fills in the
> zero sized array or flexible array member (GNU extensions?), but in either
> of these cases the DECL_MODE or TYPE_MODE should be irrelevant.
>
> So to me this really sounds like a bug in the expansion, certainly not
> stor-layout.

Sure, that was what I was saying all along ... but still, if we want to fix it
in stor-layout.c then we have to fix it for all cases there, not just the
zero-size array case (which I showed is not the only relevant case).

Richard.

>         Jakub

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-24 13:16                                                                 ` Richard Biener
  2013-10-24 13:38                                                                   ` Bernd Edlinger
@ 2013-10-25  7:05                                                                   ` Bernd Edlinger
  2013-10-25  9:29                                                                     ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-25  7:05 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

Hi Richard,


>> Did you just propose:
>>
>> --- stor-layout.c.orig 2013-10-22 10:46:49.233261818 +0200
>> +++ stor-layout.c 2013-10-24 14:54:00.425259062 +0200
>> @@ -471,27 +471,7 @@
>> static enum machine_mode
>> mode_for_array (tree elem_type, tree size)
>> {
>> - tree elem_size;
>> - unsigned HOST_WIDE_INT int_size, int_elem_size;
>> - bool limit_p;
>> -
>> - /* One-element arrays get the component type's mode. */
>> - elem_size = TYPE_SIZE (elem_type);
>> - if (simple_cst_equal (size, elem_size))
>> - return TYPE_MODE (elem_type);
>> -
>> - limit_p = true;
>> - if (host_integerp (size, 1) && host_integerp (elem_size, 1))
>> - {
>> - int_size = tree_low_cst (size, 1);
>> - int_elem_size = tree_low_cst (elem_size, 1);
>> - if (int_elem_size> 0
>> - && int_size % int_elem_size == 0
>> - && targetm.array_mode_supported_p (TYPE_MODE (elem_type),
>> - int_size / int_elem_size))
>> - limit_p = false;
>> - }
>> - return mode_for_size_tree (size, MODE_INT, limit_p);
>> + return BLKmode;
>> }
>>
>> ???
>
> Yes. Does it work?
>
> Richard.
>

No.

PASS: gcc.target/i386/pr14289-1.c  (test for errors, line 10)
FAIL: gcc.target/i386/pr14289-1.c (test for excess errors)
Excess errors:
/home/ed/gnu/gcc-4.9-20131013/gcc/testsuite/gcc.target/i386/pr14289-1.c:5:14: error: data type of 'a' isn't suitable for a register

Does that look like an ABI-Change?

the test case uses:
register int a[2] asm("ebx");

Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-25  7:05                                                                   ` Bernd Edlinger
@ 2013-10-25  9:29                                                                     ` Richard Biener
  2013-10-25 10:40                                                                       ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Richard Biener @ 2013-10-25  9:29 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

On Fri, Oct 25, 2013 at 8:29 AM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi Richard,
>
>
>>> Did you just propose:
>>>
>>> --- stor-layout.c.orig 2013-10-22 10:46:49.233261818 +0200
>>> +++ stor-layout.c 2013-10-24 14:54:00.425259062 +0200
>>> @@ -471,27 +471,7 @@
>>> static enum machine_mode
>>> mode_for_array (tree elem_type, tree size)
>>> {
>>> - tree elem_size;
>>> - unsigned HOST_WIDE_INT int_size, int_elem_size;
>>> - bool limit_p;
>>> -
>>> - /* One-element arrays get the component type's mode. */
>>> - elem_size = TYPE_SIZE (elem_type);
>>> - if (simple_cst_equal (size, elem_size))
>>> - return TYPE_MODE (elem_type);
>>> -
>>> - limit_p = true;
>>> - if (host_integerp (size, 1) && host_integerp (elem_size, 1))
>>> - {
>>> - int_size = tree_low_cst (size, 1);
>>> - int_elem_size = tree_low_cst (elem_size, 1);
>>> - if (int_elem_size> 0
>>> - && int_size % int_elem_size == 0
>>> - && targetm.array_mode_supported_p (TYPE_MODE (elem_type),
>>> - int_size / int_elem_size))
>>> - limit_p = false;
>>> - }
>>> - return mode_for_size_tree (size, MODE_INT, limit_p);
>>> + return BLKmode;
>>> }
>>>
>>> ???
>>
>> Yes. Does it work?
>>
>> Richard.
>>
>
> No.
>
> PASS: gcc.target/i386/pr14289-1.c  (test for errors, line 10)
> FAIL: gcc.target/i386/pr14289-1.c (test for excess errors)
> Excess errors:
> /home/ed/gnu/gcc-4.9-20131013/gcc/testsuite/gcc.target/i386/pr14289-1.c:5:14: error: data type of 'a' isn't suitable for a register
>
> Does that look like an ABI-Change?
>
> the test case uses:
> register int a[2] asm("ebx");

Eh ... even

register struct { int i; int a[0]; } asm ("ebx");

works.  Also with int a[1] but not with a[2].  So just handling trailing
arrays makes this case regress as well.

Now I'd call this use questionable ... but we've likely supported that
for decades and cannot change that now.

Back to fixing everything in expand.

Richard.

> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-25  9:29                                                                     ` Richard Biener
@ 2013-10-25 10:40                                                                       ` Bernd Edlinger
  2013-10-25 11:10                                                                         ` Richard Biener
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-25 10:40 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 2479 bytes --]

Hi,

> Eh ... even
>
> register struct { int i; int a[0]; } asm ("ebx");
>
> works. Also with int a[1] but not with a[2]. So just handling trailing
> arrays makes this case regress as well.
>
> Now I'd call this use questionable ... but we've likely supported that
> for decades and cannot change that now.
>
> Back to fixing everything in expand.
>
> Richard.
>

Ok, finally you asked for it.

Here is my previous version of that patch again.

I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
constant values.

I have done the same modification to VIEW_CONVERT_EXPR too, because
this is a possible inner reference, itself. It is however inherently hard to
test around this code.

To understand this patch it is good to know what type of object the
return value "tem" of get_inner_reference can be.

From the program logic at get_inner_reference it is clear that the
return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
further restricted because exp is gimplified.

Usually the result will be a MEM_REF or a SSA_NAME of the memory where
the structure is to be found.

When you look at where EXPAND_MEMORY is handled you see it is special-cased
in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
ARRAY_RANGE_REF.

At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
If it is an unaligned memory, we just return the unaligned reference.

This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
certainly be really hard to find test cases that exercise this code.

In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
we do not have to touch the handling of the outer modifier. However we pass
EXPAND_REFERENCE to the inner object, which should not be a recursive
use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.

TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.


Boot-strapped and regression-tested on x86_64-linux-gnu
OK for trunk?

Thanks
Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748-2.txt --]
[-- Type: text/plain, Size: 381 bytes --]

2013-10-25  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR middle-end/57748
	* expr.h (expand_modifier): New enum value EXPAND_REFERENCE.
	* expr.c (expand_expr_real_1): Use EXAND_REFERENCE on base object.

testsuite:
2013-10-25  Bernd Edlinger  <bernd.edlinger@hotmail.de>

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


[-- Attachment #3: patch-pr57748-2.diff --]
[-- Type: application/octet-stream, Size: 5240 bytes --]

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 203044)
+++ gcc/expr.c	(working copy)
@@ -9573,6 +9573,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	align = get_object_alignment (exp);
 	if (modifier != EXPAND_WRITE
 	    && modifier != EXPAND_MEMORY
+	    && modifier != EXPAND_REFERENCE
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode)
 	    /* If the target does not have special handling for unaligned
@@ -9653,6 +9654,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	  MEM_VOLATILE_P (temp) = 1;
 	if (modifier != EXPAND_WRITE
 	    && modifier != EXPAND_MEMORY
+	    && modifier != EXPAND_REFERENCE
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode))
 	  {
@@ -9886,7 +9888,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 			  && modifier != EXPAND_STACK_PARM
 			  ? target : NULL_RTX),
 			 VOIDmode,
-			 modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+			 EXPAND_REFERENCE);
 
 	/* If the bitfield is volatile, we want to access it in the
 	   field's mode, not the computed mode.
@@ -10245,7 +10247,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 			      && modifier != EXPAND_STACK_PARM
 			      ? target : NULL_RTX),
 			     VOIDmode,
-			     modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+			     EXPAND_REFERENCE);
 
 	    if (MEM_P (orig_op0))
 	      {
@@ -10339,7 +10341,10 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	      op0 = copy_rtx (op0);
 	      set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
 	    }
-	  else if (mode != BLKmode
+	  else if (modifier != EXPAND_WRITE
+		   && modifier != EXPAND_MEMORY
+		   && modifier != EXPAND_REFERENCE
+		   && mode != BLKmode
 		   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)
 		   /* If the target does have special handling for unaligned
 		      loads of mode then use them.  */
@@ -10360,6 +10365,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	      return reg;
 	    }
 	  else if (STRICT_ALIGNMENT
+		   && modifier != EXPAND_WRITE
+		   && modifier != EXPAND_MEMORY
+		   && modifier != EXPAND_REFERENCE
 		   && mode != BLKmode
 		   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
 	    {
Index: gcc/expr.h
===================================================================
--- gcc/expr.h	(revision 203044)
+++ gcc/expr.h	(working copy)
@@ -41,10 +41,13 @@ along with GCC; see the file COPYING3.  If not see
     is a constant that is not a legitimate address.
    EXPAND_WRITE means we are only going to write to the resulting rtx.
    EXPAND_MEMORY means we are interested in a memory result, even if
-    the memory is constant and we could have propagated a constant value.  */
+    the memory is constant and we could have propagated a constant value,
+    or the memory is unaligned on a STRICT_ALIGNMENT target.
+   EXPAND_REFERENCE is similar to EXPAND_MEMORY, used internally to expand
+    the inner reference of a component.  */
 enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
 		      EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
-		      EXPAND_MEMORY};
+		      EXPAND_MEMORY, EXPAND_REFERENCE};
 
 /* Prevent the compiler from deferring stack pops.  See
    inhibit_defer_pop for more information.  */
Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
@@ -0,0 +1,40 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#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 (P *p)
+{
+  if (p->b[0][0] != 3 || p->b[0][1] != 4)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct T *t)
+{
+  V a = { 3, 4 };
+  t->s.b[0] = a;
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+
+  foo (t);
+  check (&t->s);
+
+  free (t);
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/torture/pr57748-4.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57748-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-4.c	(revision 0)
@@ -0,0 +1,38 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#include <stdlib.h>
+
+extern void abort (void);
+
+typedef long long V
+  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+typedef struct S { V b[1]; } P __attribute__((aligned (1)));
+
+struct __attribute__((packed)) T { char c; P s; };
+
+void __attribute__((noinline, noclone))
+good_value (V b)
+{
+  if (b[0] != 3 || b[1] != 4)
+    abort ();
+}
+ 
+void __attribute__((noinline, noclone))
+check (P *p)
+{
+  good_value (p->b[1]);
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+  V a = { 3, 4 };
+  t->s.b[1] = a;
+  check (&t->s);
+  free (t);
+  return 0;
+}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access
  2013-10-24 10:06                           ` Richard Biener
  2013-10-24 10:22                             ` Bernd Edlinger
@ 2013-10-25 10:40                             ` Eric Botcazou
  1 sibling, 0 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-10-25 10:40 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor

> Doesn't that also apply to arithmetic on symbols when the offset is NULL?

This can presumably be retrofitted when the offset is null or constant.

> But yes, the codegen example posted shows this kind of difference
> (though it doesn't seem to save anything for that case).  I'd have expected
> a more explicit guarding of this case, like with MEM_P (to_rtx)
> && SYMBOL_REF_P (XEXP (to_rtx, 0)) though, eventually even looking
> whether the resulting address is legitimate.  But ... doesn't forwprop
> fix this up later anyway?

Not clear IMO, it would need to reassociate.

> The comment before it is also odd and likely only applies to later
> added restrictions.  Just to quote it again:
> 
>    if (offset != 0)
>      {
> ...
>           /* A constant address in TO_RTX can have VOIDmode, we must not try
> to call force_reg for that case.  Avoid that case.  */ if (MEM_P (to_rtx)
>               && GET_MODE (to_rtx) == BLKmode
>               && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
>               && bitsize > 0
>               && (bitpos % bitsize) == 0
>               && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
>               && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
>             {
>               to_rtx = adjust_address (to_rtx, mode1, bitpos /
> BITS_PER_UNIT); bitpos = 0;
>             }
> 
>           to_rtx = offset_address (to_rtx, offset_rtx,
>                                    highest_pow2_factor_for_target (to,
>                                                                    offset));
> }

Yes, the comment is out-of-sync and not very informative.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-25 10:40                                                                       ` Bernd Edlinger
@ 2013-10-25 11:10                                                                         ` Richard Biener
  2013-10-25 14:01                                                                           ` Martin Jambor
                                                                                             ` (2 more replies)
  0 siblings, 3 replies; 105+ messages in thread
From: Richard Biener @ 2013-10-25 11:10 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi,
>
>> Eh ... even
>>
>> register struct { int i; int a[0]; } asm ("ebx");
>>
>> works. Also with int a[1] but not with a[2]. So just handling trailing
>> arrays makes this case regress as well.
>>
>> Now I'd call this use questionable ... but we've likely supported that
>> for decades and cannot change that now.
>>
>> Back to fixing everything in expand.
>>
>> Richard.
>>
>
> Ok, finally you asked for it.
>
> Here is my previous version of that patch again.
>
> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
> constant values.
>
> I have done the same modification to VIEW_CONVERT_EXPR too, because
> this is a possible inner reference, itself. It is however inherently hard to
> test around this code.
>
> To understand this patch it is good to know what type of object the
> return value "tem" of get_inner_reference can be.
>
> From the program logic at get_inner_reference it is clear that the
> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
> further restricted because exp is gimplified.
>
> Usually the result will be a MEM_REF or a SSA_NAME of the memory where
> the structure is to be found.
>
> When you look at where EXPAND_MEMORY is handled you see it is special-cased
> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
> ARRAY_RANGE_REF.
>
> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
> If it is an unaligned memory, we just return the unaligned reference.
>
> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
> certainly be really hard to find test cases that exercise this code.
>
> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
> we do not have to touch the handling of the outer modifier. However we pass
> EXPAND_REFERENCE to the inner object, which should not be a recursive
> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.
>
> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.
>
>
> Boot-strapped and regression-tested on x86_64-linux-gnu
> OK for trunk?

You point to a weak spot in expansion - that it handles creating
the base MEM to offset with handled components by recursing
into the case that handles bare MEM_REFs.  This makes the
bare MEM_REF handling code somewhat awkward (it's the
one to assign mem-attrs which are later adjusted for example).

Maybe a better appropach than adding yet another expand
modifier would be to split out the "base MEM" expansion part
out of the bare MEM_REF handling code so we can call that
instead of recursing.

In this light - instead of a new expand modifier don't you want
an actual flag that specifies we are coming from a call that
wants to expand a base?  That is, allow EXPAND_SUM
but with the recursion flag set?

Finally I think the recursion into the VIEW_CONVERT_EXPR case
is only there because of the keep_aligning flag of get_inner_reference
which should be obsolete now that we properly handle its effects
in get_object_alignment.  So you wouldn't need to adjust this path
if we finally can get rid of that.

What do others think?

Thanks,
Richard.

> Thanks
> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-25 11:10                                                                         ` Richard Biener
@ 2013-10-25 14:01                                                                           ` Martin Jambor
  2013-10-27 20:21                                                                           ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger
  2013-11-07 13:23                                                                           ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger
  2 siblings, 0 replies; 105+ messages in thread
From: Martin Jambor @ 2013-10-25 14:01 UTC (permalink / raw)
  To: Richard Biener; +Cc: Bernd Edlinger, Eric Botcazou, GCC Patches, Jakub Jelinek

Hi,

On Fri, Oct 25, 2013 at 12:51:13PM +0200, Richard Biener wrote:
> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
> > Hi,
> >
> >> Eh ... even
> >>
> >> register struct { int i; int a[0]; } asm ("ebx");
> >>
> >> works. Also with int a[1] but not with a[2]. So just handling trailing
> >> arrays makes this case regress as well.
> >>
> >> Now I'd call this use questionable ... but we've likely supported that
> >> for decades and cannot change that now.
> >>
> >> Back to fixing everything in expand.
> >>
> >> Richard.
> >>
> >
> > Ok, finally you asked for it.
> >
> > Here is my previous version of that patch again.
> >
> > I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
> > enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
> > constant values.
> >
> > I have done the same modification to VIEW_CONVERT_EXPR too, because
> > this is a possible inner reference, itself. It is however inherently hard to
> > test around this code.
> >
> > To understand this patch it is good to know what type of object the
> > return value "tem" of get_inner_reference can be.
> >
> > From the program logic at get_inner_reference it is clear that the
> > return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
> > ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
> > be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
> > further restricted because exp is gimplified.
> >
> > Usually the result will be a MEM_REF or a SSA_NAME of the memory where
> > the structure is to be found.
> >
> > When you look at where EXPAND_MEMORY is handled you see it is special-cased
> > in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
> > ARRAY_RANGE_REF.
> >
> > At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
> > same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
> > If it is an unaligned memory, we just return the unaligned reference.
> >
> > This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
> > because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
> > certainly be really hard to find test cases that exercise this code.
> >
> > In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
> > we do not have to touch the handling of the outer modifier. However we pass
> > EXPAND_REFERENCE to the inner object, which should not be a recursive
> > use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.
> >
> > TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
> > EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.
> >
> >
> > Boot-strapped and regression-tested on x86_64-linux-gnu
> > OK for trunk?
> 
> You point to a weak spot in expansion - that it handles creating
> the base MEM to offset with handled components by recursing
> into the case that handles bare MEM_REFs.  This makes the
> bare MEM_REF handling code somewhat awkward (it's the
> one to assign mem-attrs which are later adjusted for example).
> 
> Maybe a better appropach than adding yet another expand
> modifier would be to split out the "base MEM" expansion part
> out of the bare MEM_REF handling code so we can call that
> instead of recursing.

I think that we should seize every easy opportunity to break up
expand_expr* functions into smaller ones with nicer names and easier
to understand semantics.  So I think is a good idea.

Thanks,

Martin


> 
> In this light - instead of a new expand modifier don't you want
> an actual flag that specifies we are coming from a call that
> wants to expand a base?  That is, allow EXPAND_SUM
> but with the recursion flag set?
> 
> Finally I think the recursion into the VIEW_CONVERT_EXPR case
> is only there because of the keep_aligning flag of get_inner_reference
> which should be obsolete now that we properly handle its effects
> in get_object_alignment.  So you wouldn't need to adjust this path
> if we finally can get rid of that.
> 
> What do others think?
> 
> Thanks,
> Richard.
> 
> > Thanks
> > Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-10-25 11:10                                                                         ` Richard Biener
  2013-10-25 14:01                                                                           ` Martin Jambor
@ 2013-10-27 20:21                                                                           ` Bernd Edlinger
  2013-11-26 12:37                                                                             ` Richard Biener
  2013-11-27 11:28                                                                             ` Eric Botcazou
  2013-11-07 13:23                                                                           ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger
  2 siblings, 2 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-10-27 20:21 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 739 bytes --]

Hi,

On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote:
> Finally I think the recursion into the VIEW_CONVERT_EXPR case
> is only there because of the keep_aligning flag of get_inner_reference
> which should be obsolete now that we properly handle its effects
> in get_object_alignment. So you wouldn't need to adjust this path
> if we finally can get rid of that.

I think you are right, this flag is no longer necessary, and removing
this code path would simplify everything. Therefore I'd like to propose
to remove the "keep_aligning" parameter of get_inner_reference as
a split-out patch.

Boot-strapped (with languages=all,ada,go) and
regression-tested on x86_64-linux-gnu.
Ok for trunk?

Thanks
Bernd. 		 	   		  

[-- Attachment #2: changelog-inner-reference.txt --]
[-- Type: text/plain, Size: 1546 bytes --]

2013-10-27  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	Remove parameter keep_aligning from get_inner_reference.
	* tree.h (get_inner_reference): Adjust header.
	* expr.c (get_inner_reference): Remove parameter keep_aligning.
	(get_bit_range, expand_assignment,
	expand_expr_addr_expr_1, expand_expr_real_1): Adjust.
	* asan.c (instrument_derefs): Adjust.
	* builtins.c (get_object_alignment_2): Adjust. Remove handling of
	VIEW_CONVERT_EXPR.
	* cfgexpand.c (expand_debug_expr): Adjust.
	* dbxout.c (dbxout_expand_expr): Adjust.
	* dwarf2out.c (loc_list_for_address_of_addr_expr_of_indirect_ref,
	loc_list_from_tree, fortran_common): Adjust.
	* fold-const.c (optimize_bit_field_compare,
	decode_field_reference, fold_unary_loc, fold_comparison,
	split_address_to_core_and_offset): Adjust.
	* gimple-ssa-strength-reduction.c (slsr_process_ref): Adjust.
	* simplifx-rtx.c (delegitimize_mem_from_attrs): Adjust.
	* tree-affine.c (tree_to_aff_combination,
	get_inner_reference_aff): Adjust.
	* tree-data-ref.c (split_constant_offset_1,
	dr_analyze_innermost): Adjust.
	* tree-vect-data-refs.c (vect_check_gather,
	vect_analyze_data_refs): Adjust.
	* tree-scalar-evolution.c (interpret_rhs_expr): Adjust.
	* tree-ssa-loop-ivopts.c (may_be_unaligned_p,
	split_address_cost): Adjust.
	* tsan.c (instrument_expr): Adjust.
	* ada/gcc-interface/decl.c (elaborate_expression_1): Adjust.
	* ada/gcc-interface/trans.c (Attribute_to_gnu): Adjust.
	* ada/gcc-interface/utils2.c (build_unary_op): Adjust.
	* config/mips/mips.c (r10k_safe_mem_expr_p): Adjust.


[-- Attachment #3: patch-inner-reference.diff --]
[-- Type: application/octet-stream, Size: 19213 bytes --]

Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 204101)
+++ gcc/simplify-rtx.c	(working copy)
@@ -295,7 +295,7 @@ delegitimize_mem_from_attrs (rtx x)
 	    int unsignedp, volatilep = 0;
 
 	    decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset,
-					&mode, &unsignedp, &volatilep, false);
+					&mode, &unsignedp, &volatilep);
 	    if (bitsize != GET_MODE_BITSIZE (mode)
 		|| (bitpos % BITS_PER_UNIT)
 		|| (toffset && !host_integerp (toffset, 0)))
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 204101)
+++ gcc/fold-const.c	(working copy)
@@ -3479,7 +3479,7 @@ optimize_bit_field_compare (location_t loc, enum t
      do anything if the inner expression is a PLACEHOLDER_EXPR since we
      then will no longer be able to replace it.  */
   linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
-				&lunsignedp, &lvolatilep, false);
+				&lunsignedp, &lvolatilep);
   if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
       || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep)
     return 0;
@@ -3489,7 +3489,7 @@ optimize_bit_field_compare (location_t loc, enum t
      /* If this is not a constant, we can only do something if bit positions,
 	sizes, and signedness are the same.  */
      rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
-				   &runsignedp, &rvolatilep, false);
+				   &runsignedp, &rvolatilep);
 
      if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
 	 || lunsignedp != runsignedp || offset != 0
@@ -3663,7 +3663,7 @@ decode_field_reference (location_t loc, tree exp,
     }
 
   inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
-			       punsignedp, pvolatilep, false);
+			       punsignedp, pvolatilep);
   if ((inner == exp && and_mask == 0)
       || *pbitsize < 0 || offset != 0
       || TREE_CODE (inner) == PLACEHOLDER_EXPR)
@@ -8047,7 +8047,7 @@ fold_unary_loc (location_t loc, enum tree_code cod
 	  int unsignedp, volatilep;
           tree base = TREE_OPERAND (op0, 0);
 	  base = get_inner_reference (base, &bitsize, &bitpos, &offset,
-				      &mode, &unsignedp, &volatilep, false);
+				      &mode, &unsignedp, &volatilep);
 	  /* If the reference was to a (constant) zero offset, we can use
 	     the address of the base if it has the same base type
 	     as the result type and the pointer type is unqualified.  */
@@ -9061,7 +9061,7 @@ fold_comparison (location_t loc, enum tree_code co
 	{
 	  base0 = get_inner_reference (TREE_OPERAND (arg0, 0),
 				       &bitsize, &bitpos0, &offset0, &mode,
-				       &unsignedp, &volatilep, false);
+				       &unsignedp, &volatilep);
 	  if (TREE_CODE (base0) == INDIRECT_REF)
 	    base0 = TREE_OPERAND (base0, 0);
 	  else
@@ -9095,7 +9095,7 @@ fold_comparison (location_t loc, enum tree_code co
 	{
 	  base1 = get_inner_reference (TREE_OPERAND (arg1, 0),
 				       &bitsize, &bitpos1, &offset1, &mode,
-				       &unsignedp, &volatilep, false);
+				       &unsignedp, &volatilep);
 	  if (TREE_CODE (base1) == INDIRECT_REF)
 	    base1 = TREE_OPERAND (base1, 0);
 	  else
@@ -16977,8 +16977,7 @@ split_address_to_core_and_offset (tree exp,
   if (TREE_CODE (exp) == ADDR_EXPR)
     {
       core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
-				  poffset, &mode, &unsignedp, &volatilep,
-				  false);
+				  poffset, &mode, &unsignedp, &volatilep);
       core = build_fold_addr_expr_loc (loc, core);
     }
   else
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	(revision 204101)
+++ gcc/config/mips/mips.c	(working copy)
@@ -14925,7 +14925,7 @@ r10k_safe_mem_expr_p (tree expr, HOST_WIDE_INT off
   int unsigned_p, volatile_p;
 
   inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode,
-			       &unsigned_p, &volatile_p, false);
+			       &unsigned_p, &volatile_p);
   if (!DECL_P (inner) || !DECL_SIZE_UNIT (inner) || var_offset)
     return false;
 
Index: gcc/tree-scalar-evolution.c
===================================================================
--- gcc/tree-scalar-evolution.c	(revision 204101)
+++ gcc/tree-scalar-evolution.c	(working copy)
@@ -1649,7 +1649,7 @@ interpret_rhs_expr (struct loop *loop, gimple at_s
 
 	  base = get_inner_reference (TREE_OPERAND (rhs1, 0),
 				      &bitsize, &bitpos, &offset,
-				      &mode, &unsignedp, &volatilep, false);
+				      &mode, &unsignedp, &volatilep);
 
 	  if (TREE_CODE (base) == MEM_REF)
 	    {
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c	(revision 204101)
+++ gcc/cfgexpand.c	(working copy)
@@ -3026,7 +3026,7 @@ expand_debug_expr (tree exp)
 	tree offset;
 	int volatilep = 0;
 	tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-					&mode1, &unsignedp, &volatilep, false);
+					&mode1, &unsignedp, &volatilep);
 	rtx orig_op0;
 
 	if (bitsize == 0)
Index: gcc/tree-data-ref.c
===================================================================
--- gcc/tree-data-ref.c	(revision 204101)
+++ gcc/tree-data-ref.c	(working copy)
@@ -612,7 +612,7 @@ split_constant_offset_1 (tree type, tree op0, enum
 
 	op0 = TREE_OPERAND (op0, 0);
 	base = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset,
-				    &pmode, &punsignedp, &pvolatilep, false);
+				    &pmode, &punsignedp, &pvolatilep);
 
 	if (pbitpos % BITS_PER_UNIT != 0)
 	  return false;
@@ -762,7 +762,7 @@ dr_analyze_innermost (struct data_reference *dr, s
     fprintf (dump_file, "analyze_innermost: ");
 
   base = get_inner_reference (ref, &pbitsize, &pbitpos, &poffset,
-			      &pmode, &punsignedp, &pvolatilep, false);
+			      &pmode, &punsignedp, &pvolatilep);
   gcc_assert (base != NULL_TREE);
 
   if (pbitpos % BITS_PER_UNIT != 0)
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 204101)
+++ gcc/tree.h	(working copy)
@@ -4139,8 +4139,7 @@ handled_component_p (const_tree t)
    the access position and size.  */
 
 extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
-				 tree *, enum machine_mode *, int *, int *,
-				 bool);
+				 tree *, enum machine_mode *, int *, int *);
 
 /* Return a tree of sizetype representing the size, in bytes, of the element
    of EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 204101)
+++ gcc/builtins.c	(working copy)
@@ -315,7 +315,7 @@ get_object_alignment_2 (tree exp, unsigned int *al
   /* Get the innermost object and the constant (bitpos) and possibly
      variable (offset) offset of the access.  */
   exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-			     &mode, &unsignedp, &volatilep, true);
+			     &mode, &unsignedp, &volatilep);
 
   /* Extract alignment information from the innermost object and
      possibly adjust bitpos and offset.  */
@@ -346,10 +346,6 @@ get_object_alignment_2 (tree exp, unsigned int *al
       align = DECL_ALIGN (exp);
       known_alignment = true;
     }
-  else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
-    {
-      align = TYPE_ALIGN (TREE_TYPE (exp));
-    }
   else if (TREE_CODE (exp) == INDIRECT_REF
 	   || TREE_CODE (exp) == MEM_REF
 	   || TREE_CODE (exp) == TARGET_MEM_REF)
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 204101)
+++ gcc/expr.c	(working copy)
@@ -4551,7 +4551,7 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
       int unsignedp;
       int volatilep = 0;
       get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos,
-			   &roffset, &rmode, &unsignedp, &volatilep, false);
+			   &roffset, &rmode, &unsignedp, &volatilep);
       if ((rbitpos % BITS_PER_UNIT) != 0)
 	{
 	  *bitstart = *bitend = 0;
@@ -4716,7 +4716,7 @@ expand_assignment (tree to, tree from, bool nontem
 
       push_temp_slots ();
       tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
-				 &unsignedp, &volatilep, true);
+				 &unsignedp, &volatilep);
 
       if (TREE_CODE (to) == COMPONENT_REF
 	  && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
@@ -6520,27 +6520,13 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HO
 
    If the field describes a variable-sized object, *PMODE is set to
    BLKmode and *PBITSIZE is set to -1.  An access cannot be made in
-   this case, but the address of the object can be found.
+   this case, but the address of the object can be found.  */
 
-   If KEEP_ALIGNING is true and the target is STRICT_ALIGNMENT, we don't
-   look through nodes that serve as markers of a greater alignment than
-   the one that can be deduced from the expression.  These nodes make it
-   possible for front-ends to prevent temporaries from being created by
-   the middle-end on alignment considerations.  For that purpose, the
-   normal operating mode at high-level is to always pass FALSE so that
-   the ultimate containing object is really returned; moreover, the
-   associated predicate handled_component_p will always return TRUE
-   on these nodes, thus indicating that they are essentially handled
-   by get_inner_reference.  TRUE should only be passed when the caller
-   is scanning the expression in order to build another representation
-   and specifically knows how to handle these nodes; as such, this is
-   the normal operating mode in the RTL expanders.  */
-
 tree
 get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
 		     HOST_WIDE_INT *pbitpos, tree *poffset,
 		     enum machine_mode *pmode, int *punsignedp,
-		     int *pvolatilep, bool keep_aligning)
+		     int *pvolatilep)
 {
   tree size_tree = 0;
   enum machine_mode mode = VOIDmode;
@@ -6660,14 +6646,6 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbit
 	  break;
 
 	case VIEW_CONVERT_EXPR:
-	  if (keep_aligning && STRICT_ALIGNMENT
-	      && (TYPE_ALIGN (TREE_TYPE (exp))
-	       > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))))
-	      && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
-		  < BIGGEST_ALIGNMENT)
-	      && (TYPE_ALIGN_OK (TREE_TYPE (exp))
-		  || TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (exp, 0)))))
-	    goto done;
 	  break;
 
 	case MEM_REF:
@@ -7592,7 +7570,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enu
 	 they won't change the final object whose address will be returned
 	 (they actually exist only for that purpose).  */
       inner = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-				   &mode1, &unsignedp, &volatilep, false);
+				   &mode1, &unsignedp, &volatilep);
       break;
     }
 
@@ -9869,7 +9847,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	tree offset;
 	int volatilep = 0, must_force_mem;
 	tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-					&mode1, &unsignedp, &volatilep, true);
+					&mode1, &unsignedp, &volatilep);
 	rtx orig_op0, memloc;
 	bool mem_attrs_from_type = false;
 
@@ -10230,8 +10208,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	int volatilep = 0;
 	tree tem
 	  = get_inner_reference (treeop0, &bitsize, &bitpos,
-				 &offset, &mode1, &unsignedp, &volatilep,
-				 true);
+				 &offset, &mode1, &unsignedp, &volatilep);
 	rtx orig_op0;
 
 	/* ??? We should work harder and deal with non-zero offsets.  */
Index: gcc/tsan.c
===================================================================
--- gcc/tsan.c	(revision 204101)
+++ gcc/tsan.c	(working copy)
@@ -113,7 +113,7 @@ instrument_expr (gimple_stmt_iterator gsi, tree ex
   enum machine_mode mode;
   int volatilep = 0, unsignedp = 0;
   base = get_inner_reference (expr, &bitsize, &bitpos, &offset,
-			      &mode, &unsignedp, &volatilep, false);
+			      &mode, &unsignedp, &volatilep);
 
   /* No need to instrument accesses to decls that don't escape,
      they can't escape to other threads then.  */
Index: gcc/asan.c
===================================================================
--- gcc/asan.c	(revision 204101)
+++ gcc/asan.c	(working copy)
@@ -1445,7 +1445,7 @@ instrument_derefs (gimple_stmt_iterator *iter, tre
   enum machine_mode mode;
   int volatilep = 0, unsignedp = 0;
   get_inner_reference (t, &bitsize, &bitpos, &offset,
-		       &mode, &unsignedp, &volatilep, false);
+		       &mode, &unsignedp, &volatilep);
   if (bitpos % (size_in_bytes * BITS_PER_UNIT)
       || bitsize != size_in_bytes * BITS_PER_UNIT)
     {
Index: gcc/gimple-ssa-strength-reduction.c
===================================================================
--- gcc/gimple-ssa-strength-reduction.c	(revision 204101)
+++ gcc/gimple-ssa-strength-reduction.c	(working copy)
@@ -931,7 +931,7 @@ slsr_process_ref (gimple gs)
     return;
 
   base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode,
-			      &unsignedp, &volatilep, false);
+			      &unsignedp, &volatilep);
   index = double_int::from_uhwi (bitpos);
 
   if (!restructure_reference (&base, &offset, &index, &type))
Index: gcc/tree-affine.c
===================================================================
--- gcc/tree-affine.c	(revision 204101)
+++ gcc/tree-affine.c	(working copy)
@@ -317,8 +317,7 @@ tree_to_aff_combination (tree expr, tree type, aff
 	  return;
 	}
       core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
-				  &toffset, &mode, &unsignedp, &volatilep,
-				  false);
+				  &toffset, &mode, &unsignedp, &volatilep);
       if (bitpos % BITS_PER_UNIT != 0)
 	break;
       aff_combination_const (comb, type,
@@ -886,7 +885,7 @@ get_inner_reference_aff (tree ref, aff_tree *addr,
   int uns, vol;
   aff_tree tmp;
   tree base = get_inner_reference (ref, &bitsize, &bitpos, &toff, &mode,
-				   &uns, &vol, false);
+				   &uns, &vol);
   tree base_addr = build_fold_addr_expr (base);
 
   /* ADDR = &BASE + TOFF + BITPOS / BITS_PER_UNIT.  */
Index: gcc/ada/gcc-interface/utils2.c
===================================================================
--- gcc/ada/gcc-interface/utils2.c	(revision 204101)
+++ gcc/ada/gcc-interface/utils2.c	(working copy)
@@ -1309,8 +1309,7 @@ build_unary_op (enum tree_code op_code, tree resul
 	      int unsignedp, volatilep;
 
 	      inner = get_inner_reference (operand, &bitsize, &bitpos, &offset,
-					   &mode, &unsignedp, &volatilep,
-					   false);
+					   &mode, &unsignedp, &volatilep);
 
 	      /* If INNER is a padding type whose field has a self-referential
 		 size, convert to that inner type.  We know the offset is zero
Index: gcc/ada/gcc-interface/trans.c
===================================================================
--- gcc/ada/gcc-interface/trans.c	(revision 204101)
+++ gcc/ada/gcc-interface/trans.c	(working copy)
@@ -2061,7 +2061,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_res
 			  && TREE_CODE (gnu_prefix) == FIELD_DECL));
 
 	get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset,
-			     &mode, &unsignedp, &volatilep, false);
+			     &mode, &unsignedp, &volatilep);
 
 	if (TREE_CODE (gnu_prefix) == COMPONENT_REF)
 	  {
Index: gcc/ada/gcc-interface/decl.c
===================================================================
--- gcc/ada/gcc-interface/decl.c	(revision 204101)
+++ gcc/ada/gcc-interface/decl.c	(working copy)
@@ -6263,7 +6263,7 @@ elaborate_expression_1 (tree gnu_expr, Entity_Id g
 	  int unsignedp, volatilep;
 
 	  inner = get_inner_reference (inner, &bitsize, &bitpos, &offset,
-				       &mode, &unsignedp, &volatilep, false);
+				       &mode, &unsignedp, &volatilep);
 	  /* If the offset is variable, err on the side of caution.  */
 	  if (offset)
 	    inner = NULL_TREE;
Index: gcc/tree-vect-data-refs.c
===================================================================
--- gcc/tree-vect-data-refs.c	(revision 204101)
+++ gcc/tree-vect-data-refs.c	(working copy)
@@ -2762,7 +2762,7 @@ vect_check_gather (gimple stmt, loop_vec_info loop
      SSA_NAME OFF and put the loop invariants into a tree BASE
      that can be gimplified before the loop.  */
   base = get_inner_reference (DR_REF (dr), &pbitsize, &pbitpos, &off,
-			      &pmode, &punsignedp, &pvolatilep, false);
+			      &pmode, &punsignedp, &pvolatilep);
   gcc_assert (base != NULL_TREE && (pbitpos % BITS_PER_UNIT) == 0);
 
   if (TREE_CODE (base) == MEM_REF)
@@ -3258,7 +3258,7 @@ again:
 	    }
 
 	  outer_base = get_inner_reference (inner_base, &pbitsize, &pbitpos,
-		          &poffset, &pmode, &punsignedp, &pvolatilep, false);
+		          &poffset, &pmode, &punsignedp, &pvolatilep);
 	  gcc_assert (outer_base != NULL_TREE);
 
 	  if (pbitpos % BITS_PER_UNIT != 0)
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c	(revision 204101)
+++ gcc/tree-ssa-loop-ivopts.c	(working copy)
@@ -1655,7 +1655,7 @@ may_be_unaligned_p (tree ref, tree step)
      does to check whether the object must be loaded by parts when
      STRICT_ALIGNMENT is true.  */
   base = get_inner_reference (ref, &bitsize, &bitpos, &toffset, &mode,
-			      &unsignedp, &volatilep, true);
+			      &unsignedp, &volatilep);
   base_type = TREE_TYPE (base);
   base_align = get_object_alignment (base);
   base_align = MAX (base_align, TYPE_ALIGN (base_type));
@@ -3687,7 +3687,7 @@ split_address_cost (struct ivopts_data *data,
   int unsignedp, volatilep;
 
   core = get_inner_reference (addr, &bitsize, &bitpos, &toffset, &mode,
-			      &unsignedp, &volatilep, false);
+			      &unsignedp, &volatilep);
 
   if (toffset != 0
       || bitpos % BITS_PER_UNIT != 0
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 204101)
+++ gcc/dwarf2out.c	(working copy)
@@ -13929,7 +13929,7 @@ loc_list_for_address_of_addr_expr_of_indirect_ref
 
   obj = get_inner_reference (TREE_OPERAND (loc, 0),
 			     &bitsize, &bitpos, &offset, &mode,
-			     &unsignedp, &volatilep, false);
+			     &unsignedp, &volatilep);
   STRIP_NOPS (obj);
   if (bitpos % BITS_PER_UNIT)
     {
@@ -14206,7 +14206,7 @@ loc_list_from_tree (tree loc, int want_address)
 	int unsignedp, volatilep = 0;
 
 	obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
-				   &unsignedp, &volatilep, false);
+				   &unsignedp, &volatilep);
 
 	gcc_assert (obj != loc);
 
@@ -15516,7 +15516,7 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
     return NULL_TREE;
 
   cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset,
-			      &mode, &unsignedp, &volatilep, true);
+			      &mode, &unsignedp, &volatilep);
 
   if (cvar == NULL_TREE
       || TREE_CODE (cvar) != VAR_DECL
Index: gcc/dbxout.c
===================================================================
--- gcc/dbxout.c	(revision 204101)
+++ gcc/dbxout.c	(working copy)
@@ -2509,7 +2509,7 @@ dbxout_expand_expr (tree expr)
 	rtx x;
 
 	tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
-				   &mode, &unsignedp, &volatilep, true);
+				   &mode, &unsignedp, &volatilep);
 
 	x = dbxout_expand_expr (tem);
 	if (x == NULL || !MEM_P (x))

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 3
  2013-10-22 14:08                     ` Bernd Edlinger
  2013-10-23 16:02                       ` Richard Biener
@ 2013-11-06 15:08                       ` Bernd Edlinger
  2013-12-03 13:27                         ` [PE-POST] Adjust Bit-region in expand_assignment Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-11-06 15:08 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches, Eric Botcazou, Martin Jambor

[-- Attachment #1: Type: text/plain, Size: 3209 bytes --]

> Hi,
>
> On Tue, 17 Sep 2013 01:09:45, Martin Jambor wrote:
>>> @@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
>>>        if (MEM_P (to_rtx)
>>>            && GET_MODE (to_rtx) == BLKmode
>>>            && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
>>> +          && bitregion_start == 0
>>> +          && bitregion_end == 0
>>>            && bitsize> 0
>>>            && (bitpos % bitsize) == 0
>>>            && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
>>>
>> ...
>>
>> I'm not sure to what extent the hunk adding tests for bitregion_start
>> and bitregion_end being zero is connected to this issue. I do not see
>> any of the testcases exercising that path. If it is indeed another
>> problem, I think it should be submitted (and potentially committed) as
>> a separate patch, preferably with a testcase.
>>
>
> Meanwhile I am able to give an example where that code is executed
> with bitpos = 64, bitsize=32, bitregion_start = 32, bitregion_end = 95.
>
> Afterwards bitpos=0, bitsize=32, which is completely outside
> bitregion_start=32, bitregion_end=95.
>
> However this can only be seen in the debugger, as the store_field
> goes thru a code path that does not look at bitregion_start/end.
>
> Well that is at least extremely ugly, and I would not be sure, that
> I cannot come up with a sample that crashes or creates wrong code.
>
> Currently I think that maybe the best way to fix that would be this:
>
> --- gcc/expr.c    2013-10-21 08:27:09.546035668 +0200
> +++ gcc/expr.c    2013-10-22 15:19:56.749476525 +0200
> @@ -4762,6 +4762,9 @@ expand_assignment (tree to, tree from, b
>            && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
>          {
>            to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
> +          bitregion_start = 0;
> +          if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos)
> +        bitregion_end -= bitpos;
>            bitpos = 0;
>          }
>
> Any suggestions?
>
>
>
> Regards
> Bernd.


well, as already discussed, the following example executes the above memory block,
and leaves bitregion_start/end in an undefined state:

extern void abort (void);

struct x{
  int a;
  int :32;
  volatile int b:32;
};

struct s
{
  int a,b,c,d;
  struct x xx[1];
};

struct s ss;
volatile int k;

int main()
{
  ss.xx[k].b = 1;
//  asm volatile("":::"memory");
  if ( ss.xx[k].b != 1)
    abort ();
  return 0;
}

Although this does not cause malfunction at the time, I'd propose to play safe,
and update the bitregion_start/bitregion_end. Additionally I'd propose to remove
this comment in expand_assignment and expand_expr_real_1:

 "A constant address in TO_RTX can have VOIDmode, we must not try
  to call force_reg for that case.  Avoid that case."

This comment is completely out of sync: There is no longer any force_reg in that if-block,
and a constant address in TO_RTX has SImode or DImode in GET_MODE (XEXP (to_rtx, 0))
I do not know how to make it a VOIDmode, therefore the comment does not help either.


Boot-strapped and regression-tested on x86_64-linux-gnu.

OK for trunk?


Regards
Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748-3.txt --]
[-- Type: text/plain, Size: 216 bytes --]

2013-11-06  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR middle-end/57748
	* expr.c (expand_assignment): Remove bogus comment.
	Update bitregion_start/bitregion_end.
	(expand_expr_real_1): Remove bogus comment.


[-- Attachment #3: patch-pr57748-3.diff --]
[-- Type: application/octet-stream, Size: 1254 bytes --]

--- gcc/expr.c.jj	2013-10-31 14:57:05.000000000 +0100
+++ gcc/expr.c	2013-11-06 14:48:59.095970841 +0100
@@ -4756,8 +4756,6 @@ expand_assignment (tree to, tree from, b
 	  if (GET_MODE (offset_rtx) != address_mode)
 	    offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
-	  /* A constant address in TO_RTX can have VOIDmode, we must not try
-	     to call force_reg for that case.  Avoid that case.  */
 	  if (MEM_P (to_rtx)
 	      && GET_MODE (to_rtx) == BLKmode
 	      && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
@@ -4767,6 +4765,9 @@ expand_assignment (tree to, tree from, b
 	      && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
 	    {
 	      to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
+	      bitregion_start = 0;
+	      if (bitregion_end >= (unsigned HOST_WIDE_INT) bitpos)
+		bitregion_end -= bitpos;
 	      bitpos = 0;
 	    }
 
@@ -9926,8 +9927,6 @@ expand_expr_real_1 (tree exp, rtx target
 	      offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
 	    if (GET_MODE (op0) == BLKmode
-		/* A constant address in OP0 can have VOIDmode, we must
-		   not try to call force_reg in that case.  */
 		&& GET_MODE (XEXP (op0, 0)) != VOIDmode
 		&& bitsize != 0
 		&& (bitpos % bitsize) == 0

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-11-07 13:23                                                                           ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger
@ 2013-11-07 13:23                                                                             ` Bernd Edlinger
  2013-11-19 15:05                                                                               ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-11-07 13:23 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 4836 bytes --]

oops - this time with attachments...


> Hi,
>
> On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote:
>>
>> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger
>> <bernd.edlinger@hotmail.de> wrote:
>>> Hi,
>>>
>>>> Eh ... even
>>>>
>>>> register struct { int i; int a[0]; } asm ("ebx");
>>>>
>>>> works. Also with int a[1] but not with a[2]. So just handling trailing
>>>> arrays makes this case regress as well.
>>>>
>>>> Now I'd call this use questionable ... but we've likely supported that
>>>> for decades and cannot change that now.
>>>>
>>>> Back to fixing everything in expand.
>>>>
>>>> Richard.
>>>>
>>>
>>> Ok, finally you asked for it.
>>>
>>> Here is my previous version of that patch again.
>>>
>>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
>>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
>>> constant values.
>>>
>>> I have done the same modification to VIEW_CONVERT_EXPR too, because
>>> this is a possible inner reference, itself. It is however inherently hard to
>>> test around this code.
>>>
>>> To understand this patch it is good to know what type of object the
>>> return value "tem" of get_inner_reference can be.
>>>
>>> From the program logic at get_inner_reference it is clear that the
>>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
>>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
>>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
>>> further restricted because exp is gimplified.
>>>
>>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where
>>> the structure is to be found.
>>>
>>> When you look at where EXPAND_MEMORY is handled you see it is special-cased
>>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
>>> ARRAY_RANGE_REF.
>>>
>>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
>>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
>>> If it is an unaligned memory, we just return the unaligned reference.
>>>
>>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
>>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
>>> certainly be really hard to find test cases that exercise this code.
>>>
>>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
>>> we do not have to touch the handling of the outer modifier. However we pass
>>> EXPAND_REFERENCE to the inner object, which should not be a recursive
>>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.
>>>
>>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
>>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.
>>>
>>>
>>> Boot-strapped and regression-tested on x86_64-linux-gnu
>>> OK for trunk?
>>
>> You point to a weak spot in expansion - that it handles creating
>> the base MEM to offset with handled components by recursing
>> into the case that handles bare MEM_REFs. This makes the
>> bare MEM_REF handling code somewhat awkward (it's the
>> one to assign mem-attrs which are later adjusted for example).
>>
>> Maybe a better appropach than adding yet another expand
>> modifier would be to split out the "base MEM" expansion part
>> out of the bare MEM_REF handling code so we can call that
>> instead of recursing.
>>
>> In this light - instead of a new expand modifier don't you want
>> an actual flag that specifies we are coming from a call that
>> wants to expand a base? That is, allow EXPAND_SUM
>> but with the recursion flag set?
>>
>
> I think you are right. After some thought, I start to like that idea.
>
> This way we have at least much more flexibility, how to handle the inner
> references correctly, and if I change only the interfaces of expand_expr_real/real_1
> that will not be used at too many places, either.
>
>> Finally I think the recursion into the VIEW_CONVERT_EXPR case
>> is only there because of the keep_aligning flag of get_inner_reference
>> which should be obsolete now that we properly handle its effects
>> in get_object_alignment. So you wouldn't need to adjust this path
>> if we finally can get rid of that.
>>
>
> I proposed a patch for that, but did not hear from you:
> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html
>
> nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner
> reference, the code there should be kept in sync with the normal_inner_ref,
> and MEM_REF, IMHO.
>
> Attached, my updated patch for PR57748, Part 2.
>
> Boot-strapped and regression-tested on X86_64-pc-linux-gnu.
>
> Ok for trunk?
>
>
> Thanks
> Bernd.
>
>> What do others think?
>>
>> Thanks,
>> Richard.
>>
>>> Thanks
>>> Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748-2.txt --]
[-- Type: text/plain, Size: 579 bytes --]

2013-11-07  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR middle-end/57748
	* expr.h (expand_expr_real, expand_expr_real_1): Add new parameter
	expand_reference.
	(expand_expr, expand_normal): Adjust.
	* expr.c (expand_expr_real, expand_expr_real_1): Add new parameter
	expand_reference. Use expand_reference to expand inner references.
	(store_expr): Adjust.
	* cfgexpand.c (expand_call_stmt): Adjust.

testsuite:
2013-11-07  Bernd Edlinger  <bernd.edlinger@hotmail.de>

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


[-- Attachment #3: patch-pr57748-2.diff --]
[-- Type: application/octet-stream, Size: 10472 bytes --]

Index: gcc/expr.h
===================================================================
--- gcc/expr.h	(revision 204411)
+++ gcc/expr.h	(working copy)
@@ -41,7 +41,8 @@ along with GCC; see the file COPYING3.  If not see
     is a constant that is not a legitimate address.
    EXPAND_WRITE means we are only going to write to the resulting rtx.
    EXPAND_MEMORY means we are interested in a memory result, even if
-    the memory is constant and we could have propagated a constant value.  */
+    the memory is constant and we could have propagated a constant value,
+    or the memory is unaligned on a STRICT_ALIGNMENT target.  */
 enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
 		      EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
 		      EXPAND_MEMORY};
@@ -428,9 +429,9 @@ extern rtx force_operand (rtx, rtx);
 
 /* Work horses for expand_expr.  */
 extern rtx expand_expr_real (tree, rtx, enum machine_mode,
-			     enum expand_modifier, rtx *);
+			     enum expand_modifier, rtx *, bool);
 extern rtx expand_expr_real_1 (tree, rtx, enum machine_mode,
-			       enum expand_modifier, rtx *);
+			       enum expand_modifier, rtx *, bool);
 extern rtx expand_expr_real_2 (sepops, rtx, enum machine_mode,
 			       enum expand_modifier);
 
@@ -441,13 +442,13 @@ static inline rtx
 expand_expr (tree exp, rtx target, enum machine_mode mode,
 	     enum expand_modifier modifier)
 {
-  return expand_expr_real (exp, target, mode, modifier, NULL);
+  return expand_expr_real (exp, target, mode, modifier, NULL, false);
 }
 
 static inline rtx
 expand_normal (tree exp)
 {
-  return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL);
+  return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, false);
 }
 
 /* At the start of a function, record that we have no previously-pushed
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 204411)
+++ gcc/expr.c	(working copy)
@@ -5211,7 +5211,7 @@ store_expr (tree exp, rtx target, int call_param_p
       temp = expand_expr_real (exp, tmp_target, GET_MODE (target),
 			       (call_param_p
 				? EXPAND_STACK_PARM : EXPAND_NORMAL),
-			       &alt_rtl);
+			       &alt_rtl, false);
     }
 
   /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not
@@ -7768,11 +7768,14 @@ expand_constructor (tree exp, rtx target, enum exp
    address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the
    DECL_RTL of the VAR_DECL.  *ALT_RTL is also set if EXP is a
    COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on
-   recursively.  */
+   recursively.
 
+   If EXPAND_REFERENCE is true, we are expanding an inner reference.  */
+
 rtx
 expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
-		  enum expand_modifier modifier, rtx *alt_rtl)
+		  enum expand_modifier modifier, rtx *alt_rtl,
+		  bool expand_reference)
 {
   rtx ret;
 
@@ -7784,7 +7787,8 @@ expand_expr_real (tree exp, rtx target, enum machi
       return ret ? ret : const0_rtx;
     }
 
-  ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
+  ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl,
+			    expand_reference);
   return ret;
 }
 
@@ -9095,7 +9099,8 @@ stmt_is_replaceable_p (gimple stmt)
 
 rtx
 expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
-		    enum expand_modifier modifier, rtx *alt_rtl)
+		    enum expand_modifier modifier, rtx *alt_rtl,
+		    bool expand_reference)
 {
   rtx op0, op1, temp, decl_rtl;
   tree type;
@@ -9241,7 +9246,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 
 	  set_curr_insn_location (gimple_location (g));
 	  r = expand_expr_real (gimple_assign_rhs_to_tree (g), target,
-				tmode, modifier, NULL);
+				tmode, modifier, NULL, false);
 	  set_curr_insn_location (saved_loc);
 	  if (REG_P (r) && !REG_EXPR (r))
 	    set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r);
@@ -9462,7 +9467,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
     case SAVE_EXPR:
       {
 	tree val = treeop0;
-	rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl);
+	rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl,
+				      expand_reference);
 
 	if (!SAVE_EXPR_RESOLVED_P (exp))
 	  {
@@ -9520,6 +9526,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	align = get_object_alignment (exp);
 	if (modifier != EXPAND_WRITE
 	    && modifier != EXPAND_MEMORY
+	    && !expand_reference
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode)
 	    /* If the target does not have special handling for unaligned
@@ -9600,6 +9607,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	  MEM_VOLATILE_P (temp) = 1;
 	if (modifier != EXPAND_WRITE
 	    && modifier != EXPAND_MEMORY
+	    && !expand_reference
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode))
 	  {
@@ -9825,15 +9833,16 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	   computation, since it will need a temporary and TARGET is known
 	   to have to do.  This occurs in unchecked conversion in Ada.  */
 	orig_op0 = op0
-	  = expand_expr (tem,
-			 (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
-			  && COMPLETE_TYPE_P (TREE_TYPE (tem))
-			  && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
-			      != INTEGER_CST)
-			  && modifier != EXPAND_STACK_PARM
-			  ? target : NULL_RTX),
-			 VOIDmode,
-			 modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+	  = expand_expr_real (tem,
+			      (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+			       && COMPLETE_TYPE_P (TREE_TYPE (tem))
+			       && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+				   != INTEGER_CST)
+			       && modifier != EXPAND_STACK_PARM
+			       ? target : NULL_RTX),
+			      VOIDmode,
+			      modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier,
+			      NULL, true);
 
 	/* If the bitfield is volatile, we want to access it in the
 	   field's mode, not the computed mode.
@@ -10185,14 +10194,15 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	  {
 	    /* See the normal_inner_ref case for the rationale.  */
 	    orig_op0
-	      = expand_expr (tem,
-			     (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
-			      && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
-				  != INTEGER_CST)
-			      && modifier != EXPAND_STACK_PARM
-			      ? target : NULL_RTX),
-			     VOIDmode,
-			     modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+	      = expand_expr_real (tem,
+				  (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+				   && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+				       != INTEGER_CST)
+				   && modifier != EXPAND_STACK_PARM
+				   ? target : NULL_RTX),
+				  VOIDmode,
+				  modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier,
+				  NULL, true);
 
 	    if (MEM_P (orig_op0))
 	      {
@@ -10286,7 +10296,10 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	      op0 = copy_rtx (op0);
 	      set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
 	    }
-	  else if (mode != BLKmode
+	  else if (modifier != EXPAND_WRITE
+		   && modifier != EXPAND_MEMORY
+		   && !expand_reference
+		   && mode != BLKmode
 		   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)
 		   /* If the target does have special handling for unaligned
 		      loads of mode then use them.  */
@@ -10307,6 +10320,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	      return reg;
 	    }
 	  else if (STRICT_ALIGNMENT
+		   && modifier != EXPAND_WRITE
+		   && modifier != EXPAND_MEMORY
+		   && !expand_reference
 		   && mode != BLKmode
 		   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
 	    {
@@ -10429,7 +10445,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
       /* WITH_SIZE_EXPR expands to its first argument.  The caller should
 	 have pulled out the size to use in whatever context it needed.  */
       return expand_expr_real (treeop0, original_target, tmode,
-			       modifier, alt_rtl);
+			       modifier, alt_rtl, expand_reference);
 
     default:
       return expand_expr_real_2 (&ops, target, tmode, modifier);
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c	(revision 204411)
+++ gcc/cfgexpand.c	(working copy)
@@ -2189,7 +2189,7 @@ expand_call_stmt (gimple stmt)
   if (lhs)
     expand_assignment (lhs, exp, false);
   else
-    expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL);
+    expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL, false);
 
   mark_transaction_restart_calls (stmt);
 }
Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
@@ -0,0 +1,40 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#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 (P *p)
+{
+  if (p->b[0][0] != 3 || p->b[0][1] != 4)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct T *t)
+{
+  V a = { 3, 4 };
+  t->s.b[0] = a;
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+
+  foo (t);
+  check (&t->s);
+
+  free (t);
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/torture/pr57748-4.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57748-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-4.c	(revision 0)
@@ -0,0 +1,40 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#include <stdlib.h>
+
+extern void abort (void);
+
+typedef long long V
+  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+typedef struct S { V b[1]; } P __attribute__((aligned (1)));
+
+struct __attribute__((packed)) T { char c; P s; };
+
+void __attribute__((noinline, noclone))
+check (P *p)
+{
+  if (p->b[1][0] != 3 || p->b[1][1] != 4)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct T *t)
+{
+  V a = { 3, 4 };
+  t->s.b[1] = a;
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+
+  foo (t);
+  check (&t->s);
+
+  free (t);
+  return 0;
+}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-10-25 11:10                                                                         ` Richard Biener
  2013-10-25 14:01                                                                           ` Martin Jambor
  2013-10-27 20:21                                                                           ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger
@ 2013-11-07 13:23                                                                           ` Bernd Edlinger
  2013-11-07 13:23                                                                             ` Bernd Edlinger
  2 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-11-07 13:23 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

Hi,

On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote:
>
> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
>> Hi,
>>
>>> Eh ... even
>>>
>>> register struct { int i; int a[0]; } asm ("ebx");
>>>
>>> works. Also with int a[1] but not with a[2]. So just handling trailing
>>> arrays makes this case regress as well.
>>>
>>> Now I'd call this use questionable ... but we've likely supported that
>>> for decades and cannot change that now.
>>>
>>> Back to fixing everything in expand.
>>>
>>> Richard.
>>>
>>
>> Ok, finally you asked for it.
>>
>> Here is my previous version of that patch again.
>>
>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
>> constant values.
>>
>> I have done the same modification to VIEW_CONVERT_EXPR too, because
>> this is a possible inner reference, itself. It is however inherently hard to
>> test around this code.
>>
>> To understand this patch it is good to know what type of object the
>> return value "tem" of get_inner_reference can be.
>>
>> From the program logic at get_inner_reference it is clear that the
>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
>> further restricted because exp is gimplified.
>>
>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where
>> the structure is to be found.
>>
>> When you look at where EXPAND_MEMORY is handled you see it is special-cased
>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
>> ARRAY_RANGE_REF.
>>
>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
>> If it is an unaligned memory, we just return the unaligned reference.
>>
>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
>> certainly be really hard to find test cases that exercise this code.
>>
>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
>> we do not have to touch the handling of the outer modifier. However we pass
>> EXPAND_REFERENCE to the inner object, which should not be a recursive
>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.
>>
>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.
>>
>>
>> Boot-strapped and regression-tested on x86_64-linux-gnu
>> OK for trunk?
>
> You point to a weak spot in expansion - that it handles creating
> the base MEM to offset with handled components by recursing
> into the case that handles bare MEM_REFs. This makes the
> bare MEM_REF handling code somewhat awkward (it's the
> one to assign mem-attrs which are later adjusted for example).
>
> Maybe a better appropach than adding yet another expand
> modifier would be to split out the "base MEM" expansion part
> out of the bare MEM_REF handling code so we can call that
> instead of recursing.
>
> In this light - instead of a new expand modifier don't you want
> an actual flag that specifies we are coming from a call that
> wants to expand a base? That is, allow EXPAND_SUM
> but with the recursion flag set?
>

I think you are right. After some thought, I start to like that idea.

This way we have at least much more flexibility, how to handle the inner
references correctly, and if I change only  the interfaces of expand_expr_real/real_1
that will not be used at too many places, either.

> Finally I think the recursion into the VIEW_CONVERT_EXPR case
> is only there because of the keep_aligning flag of get_inner_reference
> which should be obsolete now that we properly handle its effects
> in get_object_alignment. So you wouldn't need to adjust this path
> if we finally can get rid of that.
>

I proposed a patch for that, but did not hear from you:
http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html

nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner
reference, the code there should be kept in sync with the normal_inner_ref,
and MEM_REF, IMHO.

Attached, my updated patch for PR57748, Part 2.

Boot-strapped and regression-tested on X86_64-pc-linux-gnu.

Ok for trunk?


Thanks
Bernd.

> What do others think?
>
> Thanks,
> Richard.
>
>> Thanks
>> Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-11-07 13:23                                                                             ` Bernd Edlinger
@ 2013-11-19 15:05                                                                               ` Bernd Edlinger
  2013-11-27 16:22                                                                                 ` [PING] " Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-11-19 15:05 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 5850 bytes --]

Hello,


this is a minor update to my previous version of this patch, (using a boolean expand_reference,
instead of adding a new expand_modifier enum value):

I forgot to pass down the expand_reference value at the second expand_expr call inside the
case VIEW_CONVERT_EXPR. Sorry for the inconvenience.



@@ -10219,7 +10229,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
       }

       if (!op0)
-       op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
+       op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier,
+                               NULL, expand_reference);

       /* If the input and output modes are both the same, we are done.  */
       if (mode == GET_MODE (op0))


Boot-strapped and regression-tested on X86_64-pc-linux-gnu.

Ok for trunk?


Thanks
Bernd.


> Date: Thu, 7 Nov 2013 13:58:55 +0100
>
> oops - this time with attachments...
>
>
>> Hi,
>>
>> On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote:
>>>
>>> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger
>>> <bernd.edlinger@hotmail.de> wrote:
>>>> Hi,
>>>>
>>>>> Eh ... even
>>>>>
>>>>> register struct { int i; int a[0]; } asm ("ebx");
>>>>>
>>>>> works. Also with int a[1] but not with a[2]. So just handling trailing
>>>>> arrays makes this case regress as well.
>>>>>
>>>>> Now I'd call this use questionable ... but we've likely supported that
>>>>> for decades and cannot change that now.
>>>>>
>>>>> Back to fixing everything in expand.
>>>>>
>>>>> Richard.
>>>>>
>>>>
>>>> Ok, finally you asked for it.
>>>>
>>>> Here is my previous version of that patch again.
>>>>
>>>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
>>>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
>>>> constant values.
>>>>
>>>> I have done the same modification to VIEW_CONVERT_EXPR too, because
>>>> this is a possible inner reference, itself. It is however inherently hard to
>>>> test around this code.
>>>>
>>>> To understand this patch it is good to know what type of object the
>>>> return value "tem" of get_inner_reference can be.
>>>>
>>>> From the program logic at get_inner_reference it is clear that the
>>>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
>>>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
>>>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
>>>> further restricted because exp is gimplified.
>>>>
>>>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where
>>>> the structure is to be found.
>>>>
>>>> When you look at where EXPAND_MEMORY is handled you see it is special-cased
>>>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
>>>> ARRAY_RANGE_REF.
>>>>
>>>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
>>>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
>>>> If it is an unaligned memory, we just return the unaligned reference.
>>>>
>>>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
>>>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
>>>> certainly be really hard to find test cases that exercise this code.
>>>>
>>>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
>>>> we do not have to touch the handling of the outer modifier. However we pass
>>>> EXPAND_REFERENCE to the inner object, which should not be a recursive
>>>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.
>>>>
>>>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
>>>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.
>>>>
>>>>
>>>> Boot-strapped and regression-tested on x86_64-linux-gnu
>>>> OK for trunk?
>>>
>>> You point to a weak spot in expansion - that it handles creating
>>> the base MEM to offset with handled components by recursing
>>> into the case that handles bare MEM_REFs. This makes the
>>> bare MEM_REF handling code somewhat awkward (it's the
>>> one to assign mem-attrs which are later adjusted for example).
>>>
>>> Maybe a better appropach than adding yet another expand
>>> modifier would be to split out the "base MEM" expansion part
>>> out of the bare MEM_REF handling code so we can call that
>>> instead of recursing.
>>>
>>> In this light - instead of a new expand modifier don't you want
>>> an actual flag that specifies we are coming from a call that
>>> wants to expand a base? That is, allow EXPAND_SUM
>>> but with the recursion flag set?
>>>
>>
>> I think you are right. After some thought, I start to like that idea.
>>
>> This way we have at least much more flexibility, how to handle the inner
>> references correctly, and if I change only the interfaces of expand_expr_real/real_1
>> that will not be used at too many places, either.
>>
>>> Finally I think the recursion into the VIEW_CONVERT_EXPR case
>>> is only there because of the keep_aligning flag of get_inner_reference
>>> which should be obsolete now that we properly handle its effects
>>> in get_object_alignment. So you wouldn't need to adjust this path
>>> if we finally can get rid of that.
>>>
>>
>> I proposed a patch for that, but did not hear from you:
>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html
>>
>> nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner
>> reference, the code there should be kept in sync with the normal_inner_ref,
>> and MEM_REF, IMHO.
>>
>> Attached, my updated patch for PR57748, Part 2.
>>
>> Boot-strapped and regression-tested on X86_64-pc-linux-gnu.
>>
>> Ok for trunk?
>>
>>
>> Thanks
>> Bernd.
>>
>>> What do others think?
>>>
>>> Thanks,
>>> Richard.
>>>
>>>> Thanks
>>>> Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748-2.txt --]
[-- Type: text/plain, Size: 579 bytes --]

2013-11-07  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR middle-end/57748
	* expr.h (expand_expr_real, expand_expr_real_1): Add new parameter
	expand_reference.
	(expand_expr, expand_normal): Adjust.
	* expr.c (expand_expr_real, expand_expr_real_1): Add new parameter
	expand_reference. Use expand_reference to expand inner references.
	(store_expr): Adjust.
	* cfgexpand.c (expand_call_stmt): Adjust.

testsuite:
2013-11-07  Bernd Edlinger  <bernd.edlinger@hotmail.de>

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


[-- Attachment #3: patch-pr57748-2.diff --]
[-- Type: application/octet-stream, Size: 10855 bytes --]

Index: gcc/expr.h
===================================================================
--- gcc/expr.h	(revision 204411)
+++ gcc/expr.h	(working copy)
@@ -41,7 +41,8 @@ along with GCC; see the file COPYING3.  If not see
     is a constant that is not a legitimate address.
    EXPAND_WRITE means we are only going to write to the resulting rtx.
    EXPAND_MEMORY means we are interested in a memory result, even if
-    the memory is constant and we could have propagated a constant value.  */
+    the memory is constant and we could have propagated a constant value,
+    or the memory is unaligned on a STRICT_ALIGNMENT target.  */
 enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
 		      EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
 		      EXPAND_MEMORY};
@@ -428,9 +429,9 @@ extern rtx force_operand (rtx, rtx);
 
 /* Work horses for expand_expr.  */
 extern rtx expand_expr_real (tree, rtx, enum machine_mode,
-			     enum expand_modifier, rtx *);
+			     enum expand_modifier, rtx *, bool);
 extern rtx expand_expr_real_1 (tree, rtx, enum machine_mode,
-			       enum expand_modifier, rtx *);
+			       enum expand_modifier, rtx *, bool);
 extern rtx expand_expr_real_2 (sepops, rtx, enum machine_mode,
 			       enum expand_modifier);
 
@@ -441,13 +442,13 @@ static inline rtx
 expand_expr (tree exp, rtx target, enum machine_mode mode,
 	     enum expand_modifier modifier)
 {
-  return expand_expr_real (exp, target, mode, modifier, NULL);
+  return expand_expr_real (exp, target, mode, modifier, NULL, false);
 }
 
 static inline rtx
 expand_normal (tree exp)
 {
-  return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL);
+  return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, false);
 }
 
 /* At the start of a function, record that we have no previously-pushed
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 204411)
+++ gcc/expr.c	(working copy)
@@ -5211,7 +5211,7 @@ store_expr (tree exp, rtx target, int call_param_p
       temp = expand_expr_real (exp, tmp_target, GET_MODE (target),
 			       (call_param_p
 				? EXPAND_STACK_PARM : EXPAND_NORMAL),
-			       &alt_rtl);
+			       &alt_rtl, false);
     }
 
   /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not
@@ -7768,11 +7768,14 @@ expand_constructor (tree exp, rtx target, enum exp
    address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the
    DECL_RTL of the VAR_DECL.  *ALT_RTL is also set if EXP is a
    COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on
-   recursively.  */
+   recursively.
 
+   If EXPAND_REFERENCE is true, we are expanding an inner reference.  */
+
 rtx
 expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
-		  enum expand_modifier modifier, rtx *alt_rtl)
+		  enum expand_modifier modifier, rtx *alt_rtl,
+		  bool expand_reference)
 {
   rtx ret;
 
@@ -7784,7 +7787,8 @@ expand_expr_real (tree exp, rtx target, enum machi
       return ret ? ret : const0_rtx;
     }
 
-  ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
+  ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl,
+			    expand_reference);
   return ret;
 }
 
@@ -9095,7 +9099,8 @@ stmt_is_replaceable_p (gimple stmt)
 
 rtx
 expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
-		    enum expand_modifier modifier, rtx *alt_rtl)
+		    enum expand_modifier modifier, rtx *alt_rtl,
+		    bool expand_reference)
 {
   rtx op0, op1, temp, decl_rtl;
   tree type;
@@ -9241,7 +9246,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 
 	  set_curr_insn_location (gimple_location (g));
 	  r = expand_expr_real (gimple_assign_rhs_to_tree (g), target,
-				tmode, modifier, NULL);
+				tmode, modifier, NULL, expand_reference);
 	  set_curr_insn_location (saved_loc);
 	  if (REG_P (r) && !REG_EXPR (r))
 	    set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r);
@@ -9462,7 +9467,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
     case SAVE_EXPR:
       {
 	tree val = treeop0;
-	rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl);
+	rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl,
+				      expand_reference);
 
 	if (!SAVE_EXPR_RESOLVED_P (exp))
 	  {
@@ -9520,6 +9526,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	align = get_object_alignment (exp);
 	if (modifier != EXPAND_WRITE
 	    && modifier != EXPAND_MEMORY
+	    && !expand_reference
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode)
 	    /* If the target does not have special handling for unaligned
@@ -9600,6 +9607,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	  MEM_VOLATILE_P (temp) = 1;
 	if (modifier != EXPAND_WRITE
 	    && modifier != EXPAND_MEMORY
+	    && !expand_reference
 	    && mode != BLKmode
 	    && align < GET_MODE_ALIGNMENT (mode))
 	  {
@@ -9825,15 +9833,16 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	   computation, since it will need a temporary and TARGET is known
 	   to have to do.  This occurs in unchecked conversion in Ada.  */
 	orig_op0 = op0
-	  = expand_expr (tem,
-			 (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
-			  && COMPLETE_TYPE_P (TREE_TYPE (tem))
-			  && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
-			      != INTEGER_CST)
-			  && modifier != EXPAND_STACK_PARM
-			  ? target : NULL_RTX),
-			 VOIDmode,
-			 modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+	  = expand_expr_real (tem,
+			      (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+			       && COMPLETE_TYPE_P (TREE_TYPE (tem))
+			       && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+				   != INTEGER_CST)
+			       && modifier != EXPAND_STACK_PARM
+			       ? target : NULL_RTX),
+			      VOIDmode,
+			      modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier,
+			      NULL, true);
 
 	/* If the bitfield is volatile, we want to access it in the
 	   field's mode, not the computed mode.
@@ -10185,14 +10194,15 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	  {
 	    /* See the normal_inner_ref case for the rationale.  */
 	    orig_op0
-	      = expand_expr (tem,
-			     (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
-			      && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
-				  != INTEGER_CST)
-			      && modifier != EXPAND_STACK_PARM
-			      ? target : NULL_RTX),
-			     VOIDmode,
-			     modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
+	      = expand_expr_real (tem,
+				  (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+				   && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+				       != INTEGER_CST)
+				   && modifier != EXPAND_STACK_PARM
+				   ? target : NULL_RTX),
+				  VOIDmode,
+				  modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier,
+				  NULL, true);
 
 	    if (MEM_P (orig_op0))
 	      {
@@ -10219,7 +10229,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
       }
 
       if (!op0)
-	op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
+	op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier,
+				NULL, expand_reference);
 
       /* If the input and output modes are both the same, we are done.  */
       if (mode == GET_MODE (op0))
@@ -10286,7 +10297,10 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	      op0 = copy_rtx (op0);
 	      set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
 	    }
-	  else if (mode != BLKmode
+	  else if (modifier != EXPAND_WRITE
+		   && modifier != EXPAND_MEMORY
+		   && !expand_reference
+		   && mode != BLKmode
 		   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)
 		   /* If the target does have special handling for unaligned
 		      loads of mode then use them.  */
@@ -10307,6 +10321,9 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
 	      return reg;
 	    }
 	  else if (STRICT_ALIGNMENT
+		   && modifier != EXPAND_WRITE
+		   && modifier != EXPAND_MEMORY
+		   && !expand_reference
 		   && mode != BLKmode
 		   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
 	    {
@@ -10429,7 +10446,7 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
       /* WITH_SIZE_EXPR expands to its first argument.  The caller should
 	 have pulled out the size to use in whatever context it needed.  */
       return expand_expr_real (treeop0, original_target, tmode,
-			       modifier, alt_rtl);
+			       modifier, alt_rtl, expand_reference);
 
     default:
       return expand_expr_real_2 (&ops, target, tmode, modifier);
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c	(revision 204411)
+++ gcc/cfgexpand.c	(working copy)
@@ -2189,7 +2189,7 @@ expand_call_stmt (gimple stmt)
   if (lhs)
     expand_assignment (lhs, exp, false);
   else
-    expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL);
+    expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL, false);
 
   mark_transaction_restart_calls (stmt);
 }
Index: gcc/testsuite/gcc.dg/torture/pr57748-3.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-3.c	(revision 0)
@@ -0,0 +1,40 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#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 (P *p)
+{
+  if (p->b[0][0] != 3 || p->b[0][1] != 4)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct T *t)
+{
+  V a = { 3, 4 };
+  t->s.b[0] = a;
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+
+  foo (t);
+  check (&t->s);
+
+  free (t);
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/torture/pr57748-4.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57748-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57748-4.c	(revision 0)
@@ -0,0 +1,40 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_expr_real_1.  */
+
+#include <stdlib.h>
+
+extern void abort (void);
+
+typedef long long V
+  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+typedef struct S { V b[1]; } P __attribute__((aligned (1)));
+
+struct __attribute__((packed)) T { char c; P s; };
+
+void __attribute__((noinline, noclone))
+check (P *p)
+{
+  if (p->b[1][0] != 3 || p->b[1][1] != 4)
+    abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (struct T *t)
+{
+  V a = { 3, 4 };
+  t->s.b[1] = a;
+}
+
+int
+main ()
+{
+  struct T *t = (struct T *) calloc (128, 1);
+
+  foo (t);
+  check (&t->s);
+
+  free (t);
+  return 0;
+}

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-10-27 20:21                                                                           ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger
@ 2013-11-26 12:37                                                                             ` Richard Biener
  2013-11-27 11:28                                                                             ` Eric Botcazou
  1 sibling, 0 replies; 105+ messages in thread
From: Richard Biener @ 2013-11-26 12:37 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

On Sun, Oct 27, 2013 at 5:01 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi,
>
> On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote:
>> Finally I think the recursion into the VIEW_CONVERT_EXPR case
>> is only there because of the keep_aligning flag of get_inner_reference
>> which should be obsolete now that we properly handle its effects
>> in get_object_alignment. So you wouldn't need to adjust this path
>> if we finally can get rid of that.
>
> I think you are right, this flag is no longer necessary, and removing
> this code path would simplify everything. Therefore I'd like to propose
> to remove the "keep_aligning" parameter of get_inner_reference as
> a split-out patch.
>
> Boot-strapped (with languages=all,ada,go) and
> regression-tested on x86_64-linux-gnu.
> Ok for trunk?

Ok.

Thanks,
Richard.

> Thanks
> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-10-27 20:21                                                                           ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger
  2013-11-26 12:37                                                                             ` Richard Biener
@ 2013-11-27 11:28                                                                             ` Eric Botcazou
  2013-11-27 12:24                                                                               ` Bernd Edlinger
  2013-11-27 13:30                                                                               ` Richard Biener
  1 sibling, 2 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-11-27 11:28 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek

> I think you are right, this flag is no longer necessary, and removing
> this code path would simplify everything. Therefore I'd like to propose
> to remove the "keep_aligning" parameter of get_inner_reference as
> a split-out patch.
> 
> Boot-strapped (with languages=all,ada,go) and
> regression-tested on x86_64-linux-gnu.

I don't understand how you can commit a patch that changes something only on 
strict-alignment platforms and test it only on x86-64.  This change *must* be 
tested with Ada on a strict-alignment platform, that's the only combination 
for which it is exercised.   If you cannot do that, then please back it out.

More generally speaking, it's not acceptable to make cleanup changes like that 
in the RTL expander without extreme care, which of course starts with proper 
testing.  The patch should not have been approved either for that reason.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-11-27 11:28                                                                             ` Eric Botcazou
@ 2013-11-27 12:24                                                                               ` Bernd Edlinger
  2013-11-27 12:33                                                                                 ` Eric Botcazou
  2013-11-27 13:30                                                                               ` Richard Biener
  1 sibling, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-11-27 12:24 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek

Hi,

On 27 Nov 2013 10:43:59, Eric Botcazou wrote:
>
>> I think you are right, this flag is no longer necessary, and removing
>> this code path would simplify everything. Therefore I'd like to propose
>> to remove the "keep_aligning" parameter of get_inner_reference as
>> a split-out patch.
>>
>> Boot-strapped (with languages=all,ada,go) and
>> regression-tested on x86_64-linux-gnu.
>
> I don't understand how you can commit a patch that changes something only on
> strict-alignment platforms and test it only on x86-64. This change *must* be
> tested with Ada on a strict-alignment platform, that's the only combination

Well, I did that. Apologies for not mentioning that.

> for which it is exercised. If you cannot do that, then please back it out.
>
> More generally speaking, it's not acceptable to make cleanup changes like that
> in the RTL expander without extreme care, which of course starts with proper
> testing. The patch should not have been approved either for that reason.
>
> --
> Eric Botcazou

The change on the ada interface is actually not critical, because all invocations
of get_inner_reference there used keep_aligning == false, as did the majority of
all other invocations.

What changes with that patch, is that get_inner_reference(...., true) could return
a VIEW_CONVERT_EXPR, which is now obsolete.

If it is causing any trouble, I can revert that change of course.

Thanks
Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-11-27 12:24                                                                               ` Bernd Edlinger
@ 2013-11-27 12:33                                                                                 ` Eric Botcazou
  0 siblings, 0 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-11-27 12:33 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek

> Well, I did that. Apologies for not mentioning that.

OK, on which strict-alignment platform did you test it with Ada enabled?

> The change on the ada interface is actually not critical, because all
> invocations of get_inner_reference there used keep_aligning == false, as
> did the majority of all other invocations.

Sure, but that's not the point...

> What changes with that patch, is that get_inner_reference(...., true) could
> return a VIEW_CONVERT_EXPR, which is now obsolete.

...that's what needs to be properly verified indeed.

> If it is causing any trouble, I can revert that change of course.

You might want to take a look at PR middle-end/17746, it took about 3 months 
almost a decade ago to find something plausible to fix this fundamental issue 
for Ada on strict-aligmnent platforms so I'd rather not go through this again.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-11-27 11:28                                                                             ` Eric Botcazou
  2013-11-27 12:24                                                                               ` Bernd Edlinger
@ 2013-11-27 13:30                                                                               ` Richard Biener
  2013-11-27 15:10                                                                                 ` Bernd Edlinger
                                                                                                   ` (2 more replies)
  1 sibling, 3 replies; 105+ messages in thread
From: Richard Biener @ 2013-11-27 13:30 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: Bernd Edlinger, GCC Patches, Martin Jambor, Jakub Jelinek

On Wed, Nov 27, 2013 at 10:43 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> I think you are right, this flag is no longer necessary, and removing
>> this code path would simplify everything. Therefore I'd like to propose
>> to remove the "keep_aligning" parameter of get_inner_reference as
>> a split-out patch.
>>
>> Boot-strapped (with languages=all,ada,go) and
>> regression-tested on x86_64-linux-gnu.
>
> I don't understand how you can commit a patch that changes something only on
> strict-alignment platforms and test it only on x86-64.  This change *must* be
> tested with Ada on a strict-alignment platform, that's the only combination
> for which it is exercised.   If you cannot do that, then please back it out.
>
> More generally speaking, it's not acceptable to make cleanup changes like that
> in the RTL expander without extreme care, which of course starts with proper
> testing.  The patch should not have been approved either for that reason.

I'm fine with reverting it for now (you were in CC of the patch submission
but silent on it, I asked for the patch to start simplifying the way
mems are expanded - ultimately to avoid the recursion and mem-attribute
compute by the recursion).

We can come back during stage1.

get_object_alignment should be able to properly handle this case
if you call it on the full reference in the normal_inner_ref: case.
All the weird duplicate code on the VIEW_CONVERT_EXPR case
should IMHO go.

Richard.

> --
> Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-11-27 13:30                                                                               ` Richard Biener
@ 2013-11-27 15:10                                                                                 ` Bernd Edlinger
  2013-11-27 16:25                                                                                 ` Eric Botcazou
  2014-04-22  7:55                                                                                 ` Bernd Edlinger
  2 siblings, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-11-27 15:10 UTC (permalink / raw)
  To: Richard Biener, Eric Botcazou; +Cc: GCC Patches, Martin Jambor, Jakub Jelinek

On Wed, 27 Nov 2013 12:47:19, Richard Biener wrote:
>
> On Wed, Nov 27, 2013 at 10:43 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>>> I think you are right, this flag is no longer necessary, and removing
>>> this code path would simplify everything. Therefore I'd like to propose
>>> to remove the "keep_aligning" parameter of get_inner_reference as
>>> a split-out patch.
>>>
>>> Boot-strapped (with languages=all,ada,go) and
>>> regression-tested on x86_64-linux-gnu.
>>
>> I don't understand how you can commit a patch that changes something only on
>> strict-alignment platforms and test it only on x86-64. This change *must* be
>> tested with Ada on a strict-alignment platform, that's the only combination
>> for which it is exercised. If you cannot do that, then please back it out.
>>
>> More generally speaking, it's not acceptable to make cleanup changes like that
>> in the RTL expander without extreme care, which of course starts with proper
>> testing. The patch should not have been approved either for that reason.
>
> I'm fine with reverting it for now (you were in CC of the patch submission
> but silent on it, I asked for the patch to start simplifying the way
> mems are expanded - ultimately to avoid the recursion and mem-attribute
> compute by the recursion).
>

Ok, then I'll revert this patch in the evening.

Bernd.

> We can come back during stage1.
>
> get_object_alignment should be able to properly handle this case
> if you call it on the full reference in the normal_inner_ref: case.
> All the weird duplicate code on the VIEW_CONVERT_EXPR case
> should IMHO go.
>
> Richard.
>
>> --
>> Eric Botcazou 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-11-19 15:05                                                                               ` Bernd Edlinger
@ 2013-11-27 16:22                                                                                 ` Bernd Edlinger
  2013-11-27 17:09                                                                                   ` Richard Biener
  2013-11-27 22:30                                                                                   ` Jeff Law
  0 siblings, 2 replies; 105+ messages in thread
From: Bernd Edlinger @ 2013-11-27 16:22 UTC (permalink / raw)
  To: Richard Biener; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

Hi,

ping...

this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html

Note: it does, as it is, _not_ depend on the keep_aligning patch.
And it would fix some really nasty wrong code generation issues.


Thanks
Bernd.

> Date: Tue, 19 Nov 2013 15:39:39 +0100
>
> Hello,
>
>
> this is a minor update to my previous version of this patch, (using a boolean expand_reference,
> instead of adding a new expand_modifier enum value):
>
> I forgot to pass down the expand_reference value at the second expand_expr call inside the
> case VIEW_CONVERT_EXPR. Sorry for the inconvenience.
>
>
>
> @@ -10219,7 +10229,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
> }
>
> if (!op0)
> - op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
> + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier,
> + NULL, expand_reference);
>
> /* If the input and output modes are both the same, we are done. */
> if (mode == GET_MODE (op0))
>
>
> Boot-strapped and regression-tested on X86_64-pc-linux-gnu.
>
> Ok for trunk?
>
>
> Thanks
> Bernd.
>
>
>> Date: Thu, 7 Nov 2013 13:58:55 +0100
>>
>> oops - this time with attachments...
>>
>>
>>> Hi,
>>>
>>> On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote:
>>>>
>>>> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger
>>>> <bernd.edlinger@hotmail.de> wrote:
>>>>> Hi,
>>>>>
>>>>>> Eh ... even
>>>>>>
>>>>>> register struct { int i; int a[0]; } asm ("ebx");
>>>>>>
>>>>>> works. Also with int a[1] but not with a[2]. So just handling trailing
>>>>>> arrays makes this case regress as well.
>>>>>>
>>>>>> Now I'd call this use questionable ... but we've likely supported that
>>>>>> for decades and cannot change that now.
>>>>>>
>>>>>> Back to fixing everything in expand.
>>>>>>
>>>>>> Richard.
>>>>>>
>>>>>
>>>>> Ok, finally you asked for it.
>>>>>
>>>>> Here is my previous version of that patch again.
>>>>>
>>>>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
>>>>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
>>>>> constant values.
>>>>>
>>>>> I have done the same modification to VIEW_CONVERT_EXPR too, because
>>>>> this is a possible inner reference, itself. It is however inherently hard to
>>>>> test around this code.
>>>>>
>>>>> To understand this patch it is good to know what type of object the
>>>>> return value "tem" of get_inner_reference can be.
>>>>>
>>>>> From the program logic at get_inner_reference it is clear that the
>>>>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
>>>>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
>>>>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
>>>>> further restricted because exp is gimplified.
>>>>>
>>>>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where
>>>>> the structure is to be found.
>>>>>
>>>>> When you look at where EXPAND_MEMORY is handled you see it is special-cased
>>>>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
>>>>> ARRAY_RANGE_REF.
>>>>>
>>>>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
>>>>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
>>>>> If it is an unaligned memory, we just return the unaligned reference.
>>>>>
>>>>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
>>>>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
>>>>> certainly be really hard to find test cases that exercise this code.
>>>>>
>>>>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
>>>>> we do not have to touch the handling of the outer modifier. However we pass
>>>>> EXPAND_REFERENCE to the inner object, which should not be a recursive
>>>>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.
>>>>>
>>>>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
>>>>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.
>>>>>
>>>>>
>>>>> Boot-strapped and regression-tested on x86_64-linux-gnu
>>>>> OK for trunk?
>>>>
>>>> You point to a weak spot in expansion - that it handles creating
>>>> the base MEM to offset with handled components by recursing
>>>> into the case that handles bare MEM_REFs. This makes the
>>>> bare MEM_REF handling code somewhat awkward (it's the
>>>> one to assign mem-attrs which are later adjusted for example).
>>>>
>>>> Maybe a better appropach than adding yet another expand
>>>> modifier would be to split out the "base MEM" expansion part
>>>> out of the bare MEM_REF handling code so we can call that
>>>> instead of recursing.
>>>>
>>>> In this light - instead of a new expand modifier don't you want
>>>> an actual flag that specifies we are coming from a call that
>>>> wants to expand a base? That is, allow EXPAND_SUM
>>>> but with the recursion flag set?
>>>>
>>>
>>> I think you are right. After some thought, I start to like that idea.
>>>
>>> This way we have at least much more flexibility, how to handle the inner
>>> references correctly, and if I change only the interfaces of expand_expr_real/real_1
>>> that will not be used at too many places, either.
>>>
>>>> Finally I think the recursion into the VIEW_CONVERT_EXPR case
>>>> is only there because of the keep_aligning flag of get_inner_reference
>>>> which should be obsolete now that we properly handle its effects
>>>> in get_object_alignment. So you wouldn't need to adjust this path
>>>> if we finally can get rid of that.
>>>>
>>>
>>> I proposed a patch for that, but did not hear from you:
>>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html
>>>
>>> nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner
>>> reference, the code there should be kept in sync with the normal_inner_ref,
>>> and MEM_REF, IMHO.
>>>
>>> Attached, my updated patch for PR57748, Part 2.
>>>
>>> Boot-strapped and regression-tested on X86_64-pc-linux-gnu.
>>>
>>> Ok for trunk?
>>>
>>>
>>> Thanks
>>> Bernd.
>>>
>>>> What do others think?
>>>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> Thanks
>>>>> Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-11-27 13:30                                                                               ` Richard Biener
  2013-11-27 15:10                                                                                 ` Bernd Edlinger
@ 2013-11-27 16:25                                                                                 ` Eric Botcazou
  2013-11-27 16:33                                                                                   ` Richard Biener
  2014-04-22  7:55                                                                                 ` Bernd Edlinger
  2 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2013-11-27 16:25 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor, Jakub Jelinek

> I'm fine with reverting it for now (you were in CC of the patch submission
> but silent on it, I asked for the patch to start simplifying the way
> mems are expanded - ultimately to avoid the recursion and mem-attribute
> compute by the recursion).

Because I'm totally lost in this thread and its many sub-threads.

> We can come back during stage1.

Sure, let's do that instead and not enter stage #3 with hazardous changes.

> get_object_alignment should be able to properly handle this case
> if you call it on the full reference in the normal_inner_ref: case.

How exactly?  Once you flatten everything with get_inner_reference at the 
beginning, the TYPE_ALIGN_OK flag on the VIEW_CONVERT_EXPR is lost.

> All the weird duplicate code on the VIEW_CONVERT_EXPR case
> should IMHO go.

What has changed since 2004 exactly?  If you do a grep for TYPE_ALIGN_OK on 
4.1 and 4.9 trees, you get exactly the same 4 occurrences in the middle-end.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-11-27 16:25                                                                                 ` Eric Botcazou
@ 2013-11-27 16:33                                                                                   ` Richard Biener
  2013-11-27 16:43                                                                                     ` Eric Botcazou
  0 siblings, 1 reply; 105+ messages in thread
From: Richard Biener @ 2013-11-27 16:33 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: GCC Patches, Bernd Edlinger, Martin Jambor, Jakub Jelinek

On Wed, Nov 27, 2013 at 1:29 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> I'm fine with reverting it for now (you were in CC of the patch submission
>> but silent on it, I asked for the patch to start simplifying the way
>> mems are expanded - ultimately to avoid the recursion and mem-attribute
>> compute by the recursion).
>
> Because I'm totally lost in this thread and its many sub-threads.
>
>> We can come back during stage1.
>
> Sure, let's do that instead and not enter stage #3 with hazardous changes.
>
>> get_object_alignment should be able to properly handle this case
>> if you call it on the full reference in the normal_inner_ref: case.
>
> How exactly?  Once you flatten everything with get_inner_reference at the
> beginning, the TYPE_ALIGN_OK flag on the VIEW_CONVERT_EXPR is lost.

Well, I want

   tem = get_inner_reference (from, ...);
   op = expand_expr (tem);
...

   set_mem_attrs (op, from);

instead of setting mem_attrs from 'tem' by some obfuscated means of
recursing through multiple levels of expanding the memory reference.

That is, completely refactor this stuff as it has become so non-obvious
what happens.

>> All the weird duplicate code on the VIEW_CONVERT_EXPR case
>> should IMHO go.
>
> What has changed since 2004 exactly?  If you do a grep for TYPE_ALIGN_OK on
> 4.1 and 4.9 trees, you get exactly the same 4 occurrences in the middle-end.

Ah, get_object_alignment used keep_aligning ...

Richard.

> --
> Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-11-27 16:33                                                                                   ` Richard Biener
@ 2013-11-27 16:43                                                                                     ` Eric Botcazou
  0 siblings, 0 replies; 105+ messages in thread
From: Eric Botcazou @ 2013-11-27 16:43 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches, Bernd Edlinger, Martin Jambor, Jakub Jelinek

> Ah, get_object_alignment used keep_aligning ...

Yes, the patch contains the rather explicit hunks:

Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 204101)
+++ gcc/builtins.c	(working copy)
@@ -315,7 +315,7 @@ get_object_alignment_2 (tree exp, unsigned int *al
   /* Get the innermost object and the constant (bitpos) and possibly
      variable (offset) offset of the access.  */
   exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-			     &mode, &unsignedp, &volatilep, true);
+			     &mode, &unsignedp, &volatilep);
 
   /* Extract alignment information from the innermost object and
      possibly adjust bitpos and offset.  */
@@ -346,10 +346,6 @@ get_object_alignment_2 (tree exp, unsigned int *al
       align = DECL_ALIGN (exp);
       known_alignment = true;
     }
-  else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
-    {
-      align = TYPE_ALIGN (TREE_TYPE (exp));
-    }
   else if (TREE_CODE (exp) == INDIRECT_REF
 	   || TREE_CODE (exp) == MEM_REF
 	   || TREE_CODE (exp) == TARGET_MEM_REF)

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-11-27 16:22                                                                                 ` [PING] " Bernd Edlinger
@ 2013-11-27 17:09                                                                                   ` Richard Biener
  2013-11-27 22:30                                                                                   ` Jeff Law
  1 sibling, 0 replies; 105+ messages in thread
From: Richard Biener @ 2013-11-27 17:09 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

On Wed, Nov 27, 2013 at 1:29 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi,
>
> ping...
>
> this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html
>
> Note: it does, as it is, _not_ depend on the keep_aligning patch.
> And it would fix some really nasty wrong code generation issues.

I'll come back to all these patches once the late features have all
hit stage3 (hopefully next week).

We have some time left to fix this and related bugs.

Thanks,
Richard.

>
> Thanks
> Bernd.
>
>> Date: Tue, 19 Nov 2013 15:39:39 +0100
>>
>> Hello,
>>
>>
>> this is a minor update to my previous version of this patch, (using a boolean expand_reference,
>> instead of adding a new expand_modifier enum value):
>>
>> I forgot to pass down the expand_reference value at the second expand_expr call inside the
>> case VIEW_CONVERT_EXPR. Sorry for the inconvenience.
>>
>>
>>
>> @@ -10219,7 +10229,8 @@ expand_expr_real_1 (tree exp, rtx target, enum mac
>> }
>>
>> if (!op0)
>> - op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
>> + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier,
>> + NULL, expand_reference);
>>
>> /* If the input and output modes are both the same, we are done. */
>> if (mode == GET_MODE (op0))
>>
>>
>> Boot-strapped and regression-tested on X86_64-pc-linux-gnu.
>>
>> Ok for trunk?
>>
>>
>> Thanks
>> Bernd.
>>
>>
>>> Date: Thu, 7 Nov 2013 13:58:55 +0100
>>>
>>> oops - this time with attachments...
>>>
>>>
>>>> Hi,
>>>>
>>>> On Fri, 25 Oct 2013 12:51:13, Richard Biener wrote:
>>>>>
>>>>> On Fri, Oct 25, 2013 at 12:02 PM, Bernd Edlinger
>>>>> <bernd.edlinger@hotmail.de> wrote:
>>>>>> Hi,
>>>>>>
>>>>>>> Eh ... even
>>>>>>>
>>>>>>> register struct { int i; int a[0]; } asm ("ebx");
>>>>>>>
>>>>>>> works. Also with int a[1] but not with a[2]. So just handling trailing
>>>>>>> arrays makes this case regress as well.
>>>>>>>
>>>>>>> Now I'd call this use questionable ... but we've likely supported that
>>>>>>> for decades and cannot change that now.
>>>>>>>
>>>>>>> Back to fixing everything in expand.
>>>>>>>
>>>>>>> Richard.
>>>>>>>
>>>>>>
>>>>>> Ok, finally you asked for it.
>>>>>>
>>>>>> Here is my previous version of that patch again.
>>>>>>
>>>>>> I have now added a new value "EXPAND_REFERENCE" to the expand_modifier
>>>>>> enumeration. It is almost like EXPAND_MEMORY but it does not interfere with
>>>>>> constant values.
>>>>>>
>>>>>> I have done the same modification to VIEW_CONVERT_EXPR too, because
>>>>>> this is a possible inner reference, itself. It is however inherently hard to
>>>>>> test around this code.
>>>>>>
>>>>>> To understand this patch it is good to know what type of object the
>>>>>> return value "tem" of get_inner_reference can be.
>>>>>>
>>>>>> From the program logic at get_inner_reference it is clear that the
>>>>>> return value may *not* be BIT_FIELD_REF, COMPONENT_REF, ARRAY_REF,
>>>>>> ARRAY_RANGE_REF, REALPART_EXPR, IMAGPART_EXPR. The result may
>>>>>> be VIEW_CONVERT_EXPR only on a STRICT_ALIGNMENT target. This is probably
>>>>>> further restricted because exp is gimplified.
>>>>>>
>>>>>> Usually the result will be a MEM_REF or a SSA_NAME of the memory where
>>>>>> the structure is to be found.
>>>>>>
>>>>>> When you look at where EXPAND_MEMORY is handled you see it is special-cased
>>>>>> in TARGET_MEM_REF, MEM_REF, ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF,
>>>>>> ARRAY_RANGE_REF.
>>>>>>
>>>>>> At TARGET_MEM_REF, MEM_REF, VIEW_CONVERT_EXPR, it should be the
>>>>>> same if EXPAND_MEMORY, EXPAND_WRITE or EXPAND_REFERENCE is given:
>>>>>> If it is an unaligned memory, we just return the unaligned reference.
>>>>>>
>>>>>> This was missing for VIEW_CONVERT_EXPR, and unfortunately I have no test case,
>>>>>> because it is only a problem for STRICT_ALIGNMENT targets, and even there it will
>>>>>> certainly be really hard to find test cases that exercise this code.
>>>>>>
>>>>>> In ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF
>>>>>> we do not have to touch the handling of the outer modifier. However we pass
>>>>>> EXPAND_REFERENCE to the inner object, which should not be a recursive
>>>>>> use of any ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF, ARRAY_RANGE_REF.
>>>>>>
>>>>>> TARGET_MEM_REF, MEM_REF and VIEW_CONVERT_EXPR know how to handle
>>>>>> EXPAND_REFERENCE, anything else handles it like EXPAND_NORMAL.
>>>>>>
>>>>>>
>>>>>> Boot-strapped and regression-tested on x86_64-linux-gnu
>>>>>> OK for trunk?
>>>>>
>>>>> You point to a weak spot in expansion - that it handles creating
>>>>> the base MEM to offset with handled components by recursing
>>>>> into the case that handles bare MEM_REFs. This makes the
>>>>> bare MEM_REF handling code somewhat awkward (it's the
>>>>> one to assign mem-attrs which are later adjusted for example).
>>>>>
>>>>> Maybe a better appropach than adding yet another expand
>>>>> modifier would be to split out the "base MEM" expansion part
>>>>> out of the bare MEM_REF handling code so we can call that
>>>>> instead of recursing.
>>>>>
>>>>> In this light - instead of a new expand modifier don't you want
>>>>> an actual flag that specifies we are coming from a call that
>>>>> wants to expand a base? That is, allow EXPAND_SUM
>>>>> but with the recursion flag set?
>>>>>
>>>>
>>>> I think you are right. After some thought, I start to like that idea.
>>>>
>>>> This way we have at least much more flexibility, how to handle the inner
>>>> references correctly, and if I change only the interfaces of expand_expr_real/real_1
>>>> that will not be used at too many places, either.
>>>>
>>>>> Finally I think the recursion into the VIEW_CONVERT_EXPR case
>>>>> is only there because of the keep_aligning flag of get_inner_reference
>>>>> which should be obsolete now that we properly handle its effects
>>>>> in get_object_alignment. So you wouldn't need to adjust this path
>>>>> if we finally can get rid of that.
>>>>>
>>>>
>>>> I proposed a patch for that, but did not hear from you:
>>>> http://gcc.gnu.org/ml/gcc-patches/2013-10/msg02267.html
>>>>
>>>> nevertheless, even if the VIEW_CONVERT_EXPR may or may not be an inner
>>>> reference, the code there should be kept in sync with the normal_inner_ref,
>>>> and MEM_REF, IMHO.
>>>>
>>>> Attached, my updated patch for PR57748, Part 2.
>>>>
>>>> Boot-strapped and regression-tested on X86_64-pc-linux-gnu.
>>>>
>>>> Ok for trunk?
>>>>
>>>>
>>>> Thanks
>>>> Bernd.
>>>>
>>>>> What do others think?
>>>>>
>>>>> Thanks,
>>>>> Richard.
>>>>>
>>>>>> Thanks
>>>>>> Bernd.

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-11-27 16:22                                                                                 ` [PING] " Bernd Edlinger
  2013-11-27 17:09                                                                                   ` Richard Biener
@ 2013-11-27 22:30                                                                                   ` Jeff Law
  2013-11-28 12:36                                                                                     ` Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Jeff Law @ 2013-11-27 22:30 UTC (permalink / raw)
  To: Bernd Edlinger, Richard Biener
  Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

On 11/27/13 05:29, Bernd Edlinger wrote:
> Hi,
>
> ping...
>
> this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html
>
> Note: it does, as it is, _not_ depend on the keep_aligning patch.
> And it would fix some really nasty wrong code generation issues.
Is there a testcase for this problem?

My recommendation is to start a separate thread which focuses on this 
issue and only this issue.

jeff

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-11-27 22:30                                                                                   ` Jeff Law
@ 2013-11-28 12:36                                                                                     ` Bernd Edlinger
  2013-12-03  6:00                                                                                       ` Jeff Law
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-11-28 12:36 UTC (permalink / raw)
  To: Jeff Law, Richard Biener
  Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

Hi,

On Wed, 27 Nov 2013 12:07:16, Jeff Law wrote:
>
> On 11/27/13 05:29, Bernd Edlinger wrote:
>> Hi,
>>
>> ping...
>>
>> this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html
>>
>> Note: it does, as it is, _not_ depend on the keep_aligning patch.
>> And it would fix some really nasty wrong code generation issues.
> Is there a testcase for this problem?

Yes,
the patch contains two test cases, one for

struct S { V a; V b[0]; } P __attribute__((aligned (1)))
and another for

struct S { V b[1]; } P __attribute__((aligned (1)))


V can be anything that has a movmisalign_optab or is SLOW_UNALIGNED_ACCESS

If V::b is used as flexible array, reading p->b[1] gives garbage.

We tried hard, to fix this in stor-layout.c by not using the mode of V
for struct S, but this created ABI-fallout. So currently the only possible
way to fix it seems to be in expansion, by letting expand_real_1 know that
we need a memory reference, even if it may be unaligned.

>
> My recommendation is to start a separate thread which focuses on this
> issue and only this issue.
>

If there are more questions of general interest, please feel free to start
in a new thread.

> jeff
>

Thanks
Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PING] [PATCH, PR 57748] Check for out of bounds access, Part 2
  2013-11-28 12:36                                                                                     ` Bernd Edlinger
@ 2013-12-03  6:00                                                                                       ` Jeff Law
  0 siblings, 0 replies; 105+ messages in thread
From: Jeff Law @ 2013-12-03  6:00 UTC (permalink / raw)
  To: Bernd Edlinger, Richard Biener
  Cc: Eric Botcazou, GCC Patches, Martin Jambor, Jakub Jelinek

On 11/28/13 03:24, Bernd Edlinger wrote:
> Hi,
>
> On Wed, 27 Nov 2013 12:07:16, Jeff Law wrote:
>>
>> On 11/27/13 05:29, Bernd Edlinger wrote:
>>> Hi,
>>>
>>> ping...
>>>
>>> this patch still open: http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02291.html
>>>
>>> Note: it does, as it is, _not_ depend on the keep_aligning patch.
>>> And it would fix some really nasty wrong code generation issues.
>> Is there a testcase for this problem?
>
> Yes,
> the patch contains two test cases, one for
>
> struct S { V a; V b[0]; } P __attribute__((aligned (1)))
> and another for
>
> struct S { V b[1]; } P __attribute__((aligned (1)))
>
>
> V can be anything that has a movmisalign_optab or is SLOW_UNALIGNED_ACCESS
>
> If V::b is used as flexible array, reading p->b[1] gives garbage.
>
> We tried hard, to fix this in stor-layout.c by not using the mode of V
> for struct S, but this created ABI-fallout. So currently the only possible
> way to fix it seems to be in expansion, by letting expand_real_1 know that
> we need a memory reference, even if it may be unaligned.
>
>>
>> My recommendation is to start a separate thread which focuses on this
>> issue and only this issue.
>>
>
> If there are more questions of general interest, please feel free to start
> in a new thread.
Well, my point is there's this thread that deals with multiple issues; 
the message with the patch itself references prior versions of the patch 
and sorting out any discussion that relates strictly to the outstanding 
patch is nontrivial.

Hence my request to repost the patch as a new independent thread. 
Include the testcase and a reference to any current bugzilla bugs.



jeff

^ permalink raw reply	[flat|nested] 105+ messages in thread

* [PE-POST] Adjust Bit-region in expand_assignment
  2013-11-06 15:08                       ` [PATCH, PR 57748] Check for out of bounds access, Part 3 Bernd Edlinger
@ 2013-12-03 13:27                         ` Bernd Edlinger
  2013-12-04  5:55                           ` Jeff Law
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-12-03 13:27 UTC (permalink / raw)
  To: Richard Biener, Jeff Law; +Cc: gcc-patches, Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 2643 bytes --]

Hi,

I almost forgot about this (rather simple) one. It falls in the category "Mostly Harmless",
but it would be nice to have the bitregion_start/end consistent in all cases, even when
it does currently not cause any mal-function.

this was:
> Subject: RE: [PATCH, PR 57748] Check for out of bounds access, Part 3
> Date: Wed, 6 Nov 2013 15:40:23 +0100
>
>> Meanwhile I am able to give an example where that code is executed
>> with bitpos = 64, bitsize=32, bitregion_start = 32, bitregion_end = 95.
>>
>> Afterwards bitpos=0, bitsize=32, which is completely outside
>> bitregion_start=32, bitregion_end=95.
>>
>> However this can only be seen in the debugger, as the store_field
>> goes thru a code path that does not look at bitregion_start/end.
>>
>> Well that is at least extremely ugly, and I would not be sure, that
>> I cannot come up with a sample that crashes or creates wrong code.
>>
>> Currently I think that maybe the best way to fix that would be this:
>>
>> --- gcc/expr.c 2013-10-21 08:27:09.546035668 +0200
>> +++ gcc/expr.c 2013-10-22 15:19:56.749476525 +0200
>> @@ -4762,6 +4762,9 @@ expand_assignment (tree to, tree from, b
>> && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
>> {
>> to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
>> + bitregion_start = 0;
>> + if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos)
>> + bitregion_end -= bitpos;
>> bitpos = 0;
>> }
>>

>
> well, as already discussed, the following example executes the above memory block,
> and leaves bitregion_start/end in an undefined state:
>

extern void abort (void);

struct x{
 int a;
 int :32;
 volatile int b:32;
};

struct s
{
  int a,b,c,d;
  struct x xx[1];
};

struct s ss;
volatile int k;

int main()
{
  ss.xx[k].b = 1;
  //  asm volatile("":::"memory");
  if ( ss.xx[k].b != 1)
  abort ();
  return 0;
}

> Although this does not cause malfunction at the time, I'd propose to play safe,
> and update the bitregion_start/bitregion_end. Additionally I'd propose to remove
> this comment in expand_assignment and expand_expr_real_1:
>
>  "A constant address in TO_RTX can have VOIDmode, we must not try
>   to call force_reg for that case.  Avoid that case."
>
> This comment is completely out of sync: There is no longer any force_reg in that if-block,
> and a constant address in TO_RTX has SImode or DImode in GET_MODE (XEXP (to_rtx, 0))
> I do not know how to make it a VOIDmode, therefore the comment does not help either.
>
>

Boot-strapped and regression-tested on x86_64-linux-gnu.

OK for trunk?


Regards
Bernd. 		 	   		  

[-- Attachment #2: changelog-pr57748-3.txt --]
[-- Type: text/plain, Size: 216 bytes --]

2013-11-06  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR middle-end/57748
	* expr.c (expand_assignment): Remove bogus comment.
	Update bitregion_start/bitregion_end.
	(expand_expr_real_1): Remove bogus comment.


[-- Attachment #3: patch-pr57748-3.diff --]
[-- Type: application/octet-stream, Size: 1254 bytes --]

--- gcc/expr.c.jj	2013-10-31 14:57:05.000000000 +0100
+++ gcc/expr.c	2013-11-06 14:48:59.095970841 +0100
@@ -4756,8 +4756,6 @@ expand_assignment (tree to, tree from, b
 	  if (GET_MODE (offset_rtx) != address_mode)
 	    offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
-	  /* A constant address in TO_RTX can have VOIDmode, we must not try
-	     to call force_reg for that case.  Avoid that case.  */
 	  if (MEM_P (to_rtx)
 	      && GET_MODE (to_rtx) == BLKmode
 	      && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
@@ -4767,6 +4765,9 @@ expand_assignment (tree to, tree from, b
 	      && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
 	    {
 	      to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
+	      bitregion_start = 0;
+	      if (bitregion_end >= (unsigned HOST_WIDE_INT) bitpos)
+		bitregion_end -= bitpos;
 	      bitpos = 0;
 	    }
 
@@ -9926,8 +9927,6 @@ expand_expr_real_1 (tree exp, rtx target
 	      offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
 	    if (GET_MODE (op0) == BLKmode
-		/* A constant address in OP0 can have VOIDmode, we must
-		   not try to call force_reg in that case.  */
 		&& GET_MODE (XEXP (op0, 0)) != VOIDmode
 		&& bitsize != 0
 		&& (bitpos % bitsize) == 0

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PE-POST] Adjust Bit-region in expand_assignment
  2013-12-03 13:27                         ` [PE-POST] Adjust Bit-region in expand_assignment Bernd Edlinger
@ 2013-12-04  5:55                           ` Jeff Law
  2013-12-04  7:50                             ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Jeff Law @ 2013-12-04  5:55 UTC (permalink / raw)
  To: Bernd Edlinger, Richard Biener; +Cc: gcc-patches, Jakub Jelinek

On 12/03/13 06:27, Bernd Edlinger wrote:
>> This comment is completely out of sync: There is no longer any force_reg in that if-block,
>> and a constant address in TO_RTX has SImode or DImode in GET_MODE (XEXP (to_rtx, 0))
>> I do not know how to make it a VOIDmode, therefore the comment does not help either.
I thought that comment looked familiar...  That's because it was mine...

The way that was triggered in the past can be found in this ancient posting:

http://gcc.gnu.org/ml/gcc-patches/1999-03n/msg00654.html

The code went through a major revamp in 2002 which removed the force_reg 
calls without updating/removing the comment.

Additionally, the way we represent and thus ultimately expand the memory 
reference has changed in ways that make it harder, if not impossible to 
have a constant address at these points.  Even if were to hack up the 
expanders to force a constant address rather than a REG it's still 
nontrivial to get into that code with a constant address.

I wouldn't be terribly surprised to find all kinds of dead code in the 
expanders.

So the comment clearly needs to get zapped.

As for the consistency of bitregion_start/bitregion_end, I'm just not
familiar enough with this code or the issues for the C++ memory model to 
comment.

jeff

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PE-POST] Adjust Bit-region in expand_assignment
  2013-12-04  5:55                           ` Jeff Law
@ 2013-12-04  7:50                             ` Bernd Edlinger
  2013-12-06  4:13                               ` Jeff Law
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-12-04  7:50 UTC (permalink / raw)
  To: Jeff Law, Richard Biener; +Cc: gcc-patches, Jakub Jelinek

On Tue, 3 Dec 2013 22:55:32, Jef Law wrote:
>
> On 12/03/13 06:27, Bernd Edlinger wrote:
>>> This comment is completely out of sync: There is no longer any force_reg in that if-block,
>>> and a constant address in TO_RTX has SImode or DImode in GET_MODE (XEXP (to_rtx, 0))
>>> I do not know how to make it a VOIDmode, therefore the comment does not help either.
> I thought that comment looked familiar... That's because it was mine...
>
> The way that was triggered in the past can be found in this ancient posting:
>
> http://gcc.gnu.org/ml/gcc-patches/1999-03n/msg00654.html
>
> The code went through a major revamp in 2002 which removed the force_reg
> calls without updating/removing the comment.
>
> Additionally, the way we represent and thus ultimately expand the memory
> reference has changed in ways that make it harder, if not impossible to
> have a constant address at these points. Even if were to hack up the
> expanders to force a constant address rather than a REG it's still
> nontrivial to get into that code with a constant address.
>
> I wouldn't be terribly surprised to find all kinds of dead code in the
> expanders.
>
> So the comment clearly needs to get zapped.
>
> As for the consistency of bitregion_start/bitregion_end, I'm just not
> familiar enough with this code or the issues for the C++ memory model to
> comment.
>
> jeff

Thanks for this info.

Regarding the consistency of bitregion_start/end ,

they should either both be zero, or

bitregion_start <= bitpos && bitpos+bitsize-1 <= bitregion_end

of course bitregion_start/end should be on byte-boundarys.

So if I set bitpos=0, I must move bitregion_start/end accordingly.

Of course bitregion_start can not become negative. Therefore I set
it to zero, store_bit_field would never try to write at negative offsets
anyway. This stuff with the bit region was introduced recently,
and this if-block has been overlooked then.


Thanks
Bernd. 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PE-POST] Adjust Bit-region in expand_assignment
  2013-12-04  7:50                             ` Bernd Edlinger
@ 2013-12-06  4:13                               ` Jeff Law
  2013-12-06  8:03                                 ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Jeff Law @ 2013-12-06  4:13 UTC (permalink / raw)
  To: Bernd Edlinger, Richard Biener; +Cc: gcc-patches, Jakub Jelinek

On 12/04/13 00:49, Bernd Edlinger wrote:
>
> Regarding the consistency of bitregion_start/end ,
>
> they should either both be zero, or
>
> bitregion_start <= bitpos && bitpos+bitsize-1 <= bitregion_end
Presumably to satisfy the consecutive bitfields are a single memory 
location stuff from C++11.  Thus the bitregion representation (C++11) 
must totally encompass the original COMPONENT_REF.  I can certainly see 
how that holds immediately after the call to get_bit_range.

When we adjust the address, we're just accounting for the bit position 
(bitpos).  ie, if bitpos was 16 and TO_RTX was (plus (reg) (32)).  We 
change TO_RTX to (plus (reg) (48)).  This is ultimately meant to 
simplify the resulting insns we generate by folding the bitpos 
adjustment into the address computation.  In effect, this results in 
accessing a subobject rather than the full object.  Presumably this is 
kosher for C++11's memory model (I really don't know).

*If* it is OK to access the subobject like this in C++11's memory model, 
then is is necessary for bitregion_{start,end} to encompass the original 
object, or should it be made consistent with the bitpos/bitsize?  And 
that seems to me to be the fundamental question.  What is really the 
purpose of the bitregion_{start,end} representation?  If it must 
represent the C++ object, then ISTM we don't want to mess with it.  If 
it doesn't, then why did we bother building this alternate 
representation to begin with?


Jeff

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PE-POST] Adjust Bit-region in expand_assignment
  2013-12-06  4:13                               ` Jeff Law
@ 2013-12-06  8:03                                 ` Bernd Edlinger
  2013-12-06  9:49                                   ` Richard Biener
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2013-12-06  8:03 UTC (permalink / raw)
  To: Jeff Law, Richard Biener; +Cc: gcc-patches, Jakub Jelinek

Hi,

On Thu, 5 Dec 2013 21:12:54, Jeff Law wrote:
>
> On 12/04/13 00:49, Bernd Edlinger wrote:
>>
>> Regarding the consistency of bitregion_start/end ,
>>
>> they should either both be zero, or
>>
>> bitregion_start <= bitpos && bitpos+bitsize-1 <= bitregion_end
> Presumably to satisfy the consecutive bitfields are a single memory
> location stuff from C++11. Thus the bitregion representation (C++11)
> must totally encompass the original COMPONENT_REF. I can certainly see
> how that holds immediately after the call to get_bit_range.
>
> When we adjust the address, we're just accounting for the bit position
> (bitpos). ie, if bitpos was 16 and TO_RTX was (plus (reg) (32)). We
> change TO_RTX to (plus (reg) (48)). This is ultimately meant to
> simplify the resulting insns we generate by folding the bitpos
> adjustment into the address computation. In effect, this results in
> accessing a subobject rather than the full object. Presumably this is
> kosher for C++11's memory model (I really don't know).
>
> *If* it is OK to access the subobject like this in C++11's memory model,
> then is is necessary for bitregion_{start,end} to encompass the original
> object, or should it be made consistent with the bitpos/bitsize? And
> that seems to me to be the fundamental question. What is really the
> purpose of the bitregion_{start,end} representation? If it must
> represent the C++ object, then ISTM we don't want to mess with it. If
> it doesn't, then why did we bother building this alternate
> representation to begin with?
>

Yes, that is correct. let's assume bitpos = 16, and bitsize = 16,
then we have bitregion_start = 16 and bitregion_end = 31.
The to_rtx points to the start of the object.

to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT)

makes to_rtx point to two bytes from the beginning.
that is compensated by

bitpos = 0.

So now [to_rtx, bitpos, bitsize] means the same thing than before.
What's wrong is that bitregion_start is still 16 and bitregion_end is still 31
in that example.
The correct values would be bitregion_start = 0 and bitregion_end = 15.
that's what this new statement is meant to do:

              bitregion_start = 0;
              if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos)
                bitregion_end -= bitpos;

I need the "if" because bitregion_end could be 0, and in that case
I want bitregion_end to stay 0.


Thanks
Bernd.

>
> Jeff 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PE-POST] Adjust Bit-region in expand_assignment
  2013-12-06  8:03                                 ` Bernd Edlinger
@ 2013-12-06  9:49                                   ` Richard Biener
  0 siblings, 0 replies; 105+ messages in thread
From: Richard Biener @ 2013-12-06  9:49 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: Jeff Law, gcc-patches, Jakub Jelinek

On Fri, Dec 6, 2013 at 9:02 AM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> Hi,
>
> On Thu, 5 Dec 2013 21:12:54, Jeff Law wrote:
>>
>> On 12/04/13 00:49, Bernd Edlinger wrote:
>>>
>>> Regarding the consistency of bitregion_start/end ,
>>>
>>> they should either both be zero, or
>>>
>>> bitregion_start <= bitpos && bitpos+bitsize-1 <= bitregion_end
>> Presumably to satisfy the consecutive bitfields are a single memory
>> location stuff from C++11. Thus the bitregion representation (C++11)
>> must totally encompass the original COMPONENT_REF. I can certainly see
>> how that holds immediately after the call to get_bit_range.
>>
>> When we adjust the address, we're just accounting for the bit position
>> (bitpos). ie, if bitpos was 16 and TO_RTX was (plus (reg) (32)). We
>> change TO_RTX to (plus (reg) (48)). This is ultimately meant to
>> simplify the resulting insns we generate by folding the bitpos
>> adjustment into the address computation. In effect, this results in
>> accessing a subobject rather than the full object. Presumably this is
>> kosher for C++11's memory model (I really don't know).
>>
>> *If* it is OK to access the subobject like this in C++11's memory model,
>> then is is necessary for bitregion_{start,end} to encompass the original
>> object, or should it be made consistent with the bitpos/bitsize? And
>> that seems to me to be the fundamental question. What is really the
>> purpose of the bitregion_{start,end} representation? If it must
>> represent the C++ object, then ISTM we don't want to mess with it. If
>> it doesn't, then why did we bother building this alternate
>> representation to begin with?
>>
>
> Yes, that is correct. let's assume bitpos = 16, and bitsize = 16,
> then we have bitregion_start = 16 and bitregion_end = 31.
> The to_rtx points to the start of the object.
>
> to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT)
>
> makes to_rtx point to two bytes from the beginning.
> that is compensated by
>
> bitpos = 0.
>
> So now [to_rtx, bitpos, bitsize] means the same thing than before.
> What's wrong is that bitregion_start is still 16 and bitregion_end is still 31
> in that example.
> The correct values would be bitregion_start = 0 and bitregion_end = 15.
> that's what this new statement is meant to do:
>
>               bitregion_start = 0;
>               if (bitregion_end>= (unsigned HOST_WIDE_INT) bitpos)
>                 bitregion_end -= bitpos;
>
> I need the "if" because bitregion_end could be 0, and in that case
> I want bitregion_end to stay 0.

The patch is ok.

Thanks,
Richard.

>
> Thanks
> Bernd.
>
>>
>> Jeff

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH] Remove "keep_aligning" from get_inner_reference
  2013-11-27 13:30                                                                               ` Richard Biener
  2013-11-27 15:10                                                                                 ` Bernd Edlinger
  2013-11-27 16:25                                                                                 ` Eric Botcazou
@ 2014-04-22  7:55                                                                                 ` Bernd Edlinger
  2014-04-22  8:11                                                                                   ` Eric Botcazou
  2 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2014-04-22  7:55 UTC (permalink / raw)
  To: Richard Biener, Eric Botcazou; +Cc: GCC Patches, Martin Jambor, Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 1972 bytes --]

Hi,


On Wed, 27 Nov 2013 12:47:19, Richard Biener wrote:
>
> On Wed, Nov 27, 2013 at 10:43 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>>> I think you are right, this flag is no longer necessary, and removing
>>> this code path would simplify everything. Therefore I'd like to propose
>>> to remove the "keep_aligning" parameter of get_inner_reference as
>>> a split-out patch.
>>>
>>> Boot-strapped (with languages=all,ada,go) and
>>> regression-tested on x86_64-linux-gnu.
>>
>> I don't understand how you can commit a patch that changes something only on
>> strict-alignment platforms and test it only on x86-64. This change *must* be
>> tested with Ada on a strict-alignment platform, that's the only combination
>> for which it is exercised. If you cannot do that, then please back it out.
>>
>> More generally speaking, it's not acceptable to make cleanup changes like that
>> in the RTL expander without extreme care, which of course starts with proper
>> testing. The patch should not have been approved either for that reason.
>
> I'm fine with reverting it for now (you were in CC of the patch submission
> but silent on it, I asked for the patch to start simplifying the way
> mems are expanded - ultimately to avoid the recursion and mem-attribute
> compute by the recursion).
>
> We can come back during stage1.
>

Well, it's stage1 again.

I still have that already-approved patch, updated to current trunk.
I've successfully boot-strapped it on armv7-linux-gnueabihf with
all languages enabled, including Ada.
The test suite runs cleanly without any drop-outs.

Is it OK to commit now, or are there objections?


Thanks
Bernd.

> get_object_alignment should be able to properly handle this case
> if you call it on the full reference in the normal_inner_ref: case.
> All the weird duplicate code on the VIEW_CONVERT_EXPR case
> should IMHO go.
>
> Richard.
>
>> --
>> Eric Botcazou


 		 	   		  

[-- Attachment #2: changelog-inner-reference.txt --]
[-- Type: text/plain, Size: 1634 bytes --]

2014-04-16  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	Remove parameter keep_aligning from get_inner_reference.
	* tree.h (get_inner_reference): Adjust header.
	* expr.c (get_inner_reference): Remove parameter keep_aligning.
	(get_bit_range, expand_assignment,
	expand_expr_addr_expr_1, expand_expr_real_1): Adjust.
	* asan.c (instrument_derefs): Adjust.
	* builtins.c (get_object_alignment_2): Adjust. Remove handling of
	VIEW_CONVERT_EXPR.
	* cfgexpand.c (expand_debug_expr): Adjust.
	* dbxout.c (dbxout_expand_expr): Adjust.
	* dwarf2out.c (loc_list_for_address_of_addr_expr_of_indirect_ref,
	loc_list_from_tree, fortran_common): Adjust.
	* fold-const.c (optimize_bit_field_compare,
	decode_field_reference, fold_unary_loc, fold_comparison,
	split_address_to_core_and_offset): Adjust.
	* gimple-ssa-strength-reduction.c (slsr_process_ref): Adjust.
	* simplifx-rtx.c (delegitimize_mem_from_attrs): Adjust.
	* tree-affine.c (tree_to_aff_combination,
	get_inner_reference_aff): Adjust.
	* tree-data-ref.c (split_constant_offset_1,
	dr_analyze_innermost): Adjust.
	* tree-vect-data-refs.c (vect_check_gather,
	vect_analyze_data_refs): Adjust.
	* tree-scalar-evolution.c (interpret_rhs_expr): Adjust.
	* tree-ssa-loop-ivopts.c ( split_address_cost): Adjust.
	* tsan.c (instrument_expr): Adjust.
	* config/mips/mips.c (r10k_safe_mem_expr_p): Adjust.

ada:
2014-04-16  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	Remove parameter keep_aligning from get_inner_reference.
	* gcc-interface/decl.c (elaborate_expression_1): Adjust.
	* gcc-interface/trans.c (Attribute_to_gnu): Adjust.
	* gcc-interface/utils2.c (build_unary_op): Adjust.

[-- Attachment #3: patch-inner-reference.diff --]
[-- Type: application/octet-stream, Size: 18974 bytes --]

diff -pur gcc/ada/gcc-interface/decl.c gcc/ada/gcc-interface/decl.c
--- gcc/ada/gcc-interface/decl.c	2014-01-25 11:42:04.000000000 +0100
+++ gcc/ada/gcc-interface/decl.c	2014-04-15 09:39:15.273336672 +0200
@@ -6301,7 +6301,7 @@ elaborate_expression_1 (tree gnu_expr, E
 	  int unsignedp, volatilep;
 
 	  inner = get_inner_reference (inner, &bitsize, &bitpos, &offset,
-				       &mode, &unsignedp, &volatilep, false);
+				       &mode, &unsignedp, &volatilep);
 	  /* If the offset is variable, err on the side of caution.  */
 	  if (offset)
 	    inner = NULL_TREE;
diff -pur gcc/ada/gcc-interface/trans.c gcc/ada/gcc-interface/trans.c
--- gcc/ada/gcc-interface/trans.c	2014-02-25 17:14:58.000000000 +0100
+++ gcc/ada/gcc-interface/trans.c	2014-04-15 09:39:15.281336643 +0200
@@ -2094,7 +2094,7 @@ Attribute_to_gnu (Node_Id gnat_node, tre
 			  && TREE_CODE (gnu_prefix) == FIELD_DECL));
 
 	get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset,
-			     &mode, &unsignedp, &volatilep, false);
+			     &mode, &unsignedp, &volatilep);
 
 	if (TREE_CODE (gnu_prefix) == COMPONENT_REF)
 	  {
diff -pur gcc/ada/gcc-interface/utils2.c gcc/ada/gcc-interface/utils2.c
--- gcc/ada/gcc-interface/utils2.c	2014-02-23 17:26:32.000000000 +0100
+++ gcc/ada/gcc-interface/utils2.c	2014-04-15 09:39:15.281336643 +0200
@@ -1312,8 +1312,7 @@ build_unary_op (enum tree_code op_code,
 	      int unsignedp, volatilep;
 
 	      inner = get_inner_reference (operand, &bitsize, &bitpos, &offset,
-					   &mode, &unsignedp, &volatilep,
-					   false);
+					   &mode, &unsignedp, &volatilep);
 
 	      /* If INNER is a padding type whose field has a self-referential
 		 size, convert to that inner type.  We know the offset is zero
diff -pur gcc/asan.c gcc/asan.c
--- gcc/asan.c	2014-01-09 08:31:05.000000000 +0100
+++ gcc/asan.c	2014-04-15 09:39:15.301336568 +0200
@@ -1605,7 +1605,7 @@ instrument_derefs (gimple_stmt_iterator
   enum machine_mode mode;
   int volatilep = 0, unsignedp = 0;
   tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset,
-				    &mode, &unsignedp, &volatilep, false);
+				    &mode, &unsignedp, &volatilep);
   if (bitpos % (size_in_bytes * BITS_PER_UNIT)
       || bitsize != size_in_bytes * BITS_PER_UNIT)
     {
diff -pur gcc/builtins.c gcc/builtins.c
--- gcc/builtins.c	2014-03-18 12:31:04.000000000 +0100
+++ gcc/builtins.c	2014-04-15 09:39:15.205336931 +0200
@@ -327,7 +327,7 @@ get_object_alignment_2 (tree exp, unsign
   /* Get the innermost object and the constant (bitpos) and possibly
      variable (offset) offset of the access.  */
   exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-			     &mode, &unsignedp, &volatilep, true);
+			     &mode, &unsignedp, &volatilep);
 
   /* Extract alignment information from the innermost object and
      possibly adjust bitpos and offset.  */
@@ -358,10 +358,6 @@ get_object_alignment_2 (tree exp, unsign
       align = DECL_ALIGN (exp);
       known_alignment = true;
     }
-  else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
-    {
-      align = TYPE_ALIGN (TREE_TYPE (exp));
-    }
   else if (TREE_CODE (exp) == INDIRECT_REF
 	   || TREE_CODE (exp) == MEM_REF
 	   || TREE_CODE (exp) == TARGET_MEM_REF)
diff -pur gcc/cfgexpand.c gcc/cfgexpand.c
--- gcc/cfgexpand.c	2014-03-20 12:35:22.000000000 +0100
+++ gcc/cfgexpand.c	2014-04-15 09:39:15.345336402 +0200
@@ -3954,7 +3954,7 @@ expand_debug_expr (tree exp)
 	tree offset;
 	int volatilep = 0;
 	tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-					&mode1, &unsignedp, &volatilep, false);
+					&mode1, &unsignedp, &volatilep);
 	rtx orig_op0;
 
 	if (bitsize == 0)
diff -pur gcc/config/mips/mips.c gcc/config/mips/mips.c
--- gcc/config/mips/mips.c	2014-03-08 10:27:23.000000000 +0100
+++ gcc/config/mips/mips.c	2014-04-15 09:39:15.365336327 +0200
@@ -15078,7 +15078,7 @@ r10k_safe_mem_expr_p (tree expr, unsigne
   int unsigned_p, volatile_p;
 
   inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode,
-			       &unsigned_p, &volatile_p, false);
+			       &unsigned_p, &volatile_p);
   if (!DECL_P (inner) || !DECL_SIZE_UNIT (inner) || var_offset)
     return false;
 
diff -pur gcc/dbxout.c gcc/dbxout.c
--- gcc/dbxout.c	2014-01-02 23:23:26.000000000 +0100
+++ gcc/dbxout.c	2014-04-15 09:39:15.241336794 +0200
@@ -2511,7 +2511,7 @@ dbxout_expand_expr (tree expr)
 	rtx x;
 
 	tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
-				   &mode, &unsignedp, &volatilep, true);
+				   &mode, &unsignedp, &volatilep);
 
 	x = dbxout_expand_expr (tem);
 	if (x == NULL || !MEM_P (x))
diff -pur gcc/dwarf2out.c gcc/dwarf2out.c
--- gcc/dwarf2out.c	2014-04-04 18:10:07.000000000 +0200
+++ gcc/dwarf2out.c	2014-04-15 09:39:15.253336749 +0200
@@ -13971,7 +13971,7 @@ loc_list_for_address_of_addr_expr_of_ind
 
   obj = get_inner_reference (TREE_OPERAND (loc, 0),
 			     &bitsize, &bitpos, &offset, &mode,
-			     &unsignedp, &volatilep, false);
+			     &unsignedp, &volatilep);
   STRIP_NOPS (obj);
   if (bitpos % BITS_PER_UNIT)
     {
@@ -14248,7 +14248,7 @@ loc_list_from_tree (tree loc, int want_a
 	int unsignedp, volatilep = 0;
 
 	obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
-				   &unsignedp, &volatilep, false);
+				   &unsignedp, &volatilep);
 
 	gcc_assert (obj != loc);
 
@@ -15558,7 +15558,7 @@ fortran_common (tree decl, HOST_WIDE_INT
     return NULL_TREE;
 
   cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset,
-			      &mode, &unsignedp, &volatilep, true);
+			      &mode, &unsignedp, &volatilep);
 
   if (cvar == NULL_TREE
       || TREE_CODE (cvar) != VAR_DECL
diff -pur gcc/expr.c gcc/expr.c
--- gcc/expr.c	2014-04-11 13:52:14.000000000 +0200
+++ gcc/expr.c	2014-04-15 09:39:15.261336719 +0200
@@ -4665,7 +4665,7 @@ get_bit_range (unsigned HOST_WIDE_INT *b
       int unsignedp;
       int volatilep = 0;
       get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos,
-			   &roffset, &rmode, &unsignedp, &volatilep, false);
+			   &roffset, &rmode, &unsignedp, &volatilep);
       if ((rbitpos % BITS_PER_UNIT) != 0)
 	{
 	  *bitstart = *bitend = 0;
@@ -4818,7 +4818,7 @@ expand_assignment (tree to, tree from, b
 
       push_temp_slots ();
       tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
-				 &unsignedp, &volatilep, true);
+				 &unsignedp, &volatilep);
 
       /* Make sure bitpos is not negative, it can wreak havoc later.  */
       if (bitpos < 0)
@@ -6674,27 +6674,13 @@ store_field (rtx target, HOST_WIDE_INT b
 
    If the field describes a variable-sized object, *PMODE is set to
    BLKmode and *PBITSIZE is set to -1.  An access cannot be made in
-   this case, but the address of the object can be found.
-
-   If KEEP_ALIGNING is true and the target is STRICT_ALIGNMENT, we don't
-   look through nodes that serve as markers of a greater alignment than
-   the one that can be deduced from the expression.  These nodes make it
-   possible for front-ends to prevent temporaries from being created by
-   the middle-end on alignment considerations.  For that purpose, the
-   normal operating mode at high-level is to always pass FALSE so that
-   the ultimate containing object is really returned; moreover, the
-   associated predicate handled_component_p will always return TRUE
-   on these nodes, thus indicating that they are essentially handled
-   by get_inner_reference.  TRUE should only be passed when the caller
-   is scanning the expression in order to build another representation
-   and specifically knows how to handle these nodes; as such, this is
-   the normal operating mode in the RTL expanders.  */
+   this case, but the address of the object can be found.  */
 
 tree
 get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
 		     HOST_WIDE_INT *pbitpos, tree *poffset,
 		     enum machine_mode *pmode, int *punsignedp,
-		     int *pvolatilep, bool keep_aligning)
+		     int *pvolatilep)
 {
   tree size_tree = 0;
   enum machine_mode mode = VOIDmode;
@@ -6814,14 +6800,6 @@ get_inner_reference (tree exp, HOST_WIDE
 	  break;
 
 	case VIEW_CONVERT_EXPR:
-	  if (keep_aligning && STRICT_ALIGNMENT
-	      && (TYPE_ALIGN (TREE_TYPE (exp))
-	       > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))))
-	      && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
-		  < BIGGEST_ALIGNMENT)
-	      && (TYPE_ALIGN_OK (TREE_TYPE (exp))
-		  || TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (exp, 0)))))
-	    goto done;
 	  break;
 
 	case MEM_REF:
@@ -7686,7 +7664,7 @@ expand_expr_addr_expr_1 (tree exp, rtx t
 	 they won't change the final object whose address will be returned
 	 (they actually exist only for that purpose).  */
       inner = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-				   &mode1, &unsignedp, &volatilep, false);
+				   &mode1, &unsignedp, &volatilep);
       break;
     }
 
@@ -9988,7 +9966,7 @@ expand_expr_real_1 (tree exp, rtx target
 	tree offset;
 	int volatilep = 0, must_force_mem;
 	tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-					&mode1, &unsignedp, &volatilep, true);
+					&mode1, &unsignedp, &volatilep);
 	rtx orig_op0, memloc;
 	bool mem_attrs_from_type = false;
 
@@ -10346,8 +10324,7 @@ expand_expr_real_1 (tree exp, rtx target
 	int volatilep = 0;
 	tree tem
 	  = get_inner_reference (treeop0, &bitsize, &bitpos,
-				 &offset, &mode1, &unsignedp, &volatilep,
-				 true);
+				 &offset, &mode1, &unsignedp, &volatilep);
 	rtx orig_op0;
 
 	/* ??? We should work harder and deal with non-zero offsets.  */
diff -pur gcc/fold-const.c gcc/fold-const.c
--- gcc/fold-const.c	2014-01-02 23:23:26.000000000 +0100
+++ gcc/fold-const.c	2014-04-15 09:39:15.221336869 +0200
@@ -3503,7 +3503,7 @@ optimize_bit_field_compare (location_t l
      do anything if the inner expression is a PLACEHOLDER_EXPR since we
      then will no longer be able to replace it.  */
   linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
-				&lunsignedp, &lvolatilep, false);
+				&lunsignedp, &lvolatilep);
   if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
       || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep)
     return 0;
@@ -3513,7 +3513,7 @@ optimize_bit_field_compare (location_t l
      /* If this is not a constant, we can only do something if bit positions,
 	sizes, and signedness are the same.  */
      rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
-				   &runsignedp, &rvolatilep, false);
+				   &runsignedp, &rvolatilep);
 
      if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
 	 || lunsignedp != runsignedp || offset != 0
@@ -3687,7 +3687,7 @@ decode_field_reference (location_t loc,
     }
 
   inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
-			       punsignedp, pvolatilep, false);
+			       punsignedp, pvolatilep);
   if ((inner == exp && and_mask == 0)
       || *pbitsize < 0 || offset != 0
       || TREE_CODE (inner) == PLACEHOLDER_EXPR)
@@ -8071,7 +8071,7 @@ fold_unary_loc (location_t loc, enum tre
 	  int unsignedp, volatilep;
           tree base = TREE_OPERAND (op0, 0);
 	  base = get_inner_reference (base, &bitsize, &bitpos, &offset,
-				      &mode, &unsignedp, &volatilep, false);
+				      &mode, &unsignedp, &volatilep);
 	  /* If the reference was to a (constant) zero offset, we can use
 	     the address of the base if it has the same base type
 	     as the result type and the pointer type is unqualified.  */
@@ -9096,7 +9096,7 @@ fold_comparison (location_t loc, enum tr
 	{
 	  base0 = get_inner_reference (TREE_OPERAND (arg0, 0),
 				       &bitsize, &bitpos0, &offset0, &mode,
-				       &unsignedp, &volatilep, false);
+				       &unsignedp, &volatilep);
 	  if (TREE_CODE (base0) == INDIRECT_REF)
 	    base0 = TREE_OPERAND (base0, 0);
 	  else
@@ -9130,7 +9130,7 @@ fold_comparison (location_t loc, enum tr
 	{
 	  base1 = get_inner_reference (TREE_OPERAND (arg1, 0),
 				       &bitsize, &bitpos1, &offset1, &mode,
-				       &unsignedp, &volatilep, false);
+				       &unsignedp, &volatilep);
 	  if (TREE_CODE (base1) == INDIRECT_REF)
 	    base1 = TREE_OPERAND (base1, 0);
 	  else
@@ -16999,8 +16999,7 @@ split_address_to_core_and_offset (tree e
   if (TREE_CODE (exp) == ADDR_EXPR)
     {
       core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
-				  poffset, &mode, &unsignedp, &volatilep,
-				  false);
+				  poffset, &mode, &unsignedp, &volatilep);
       core = build_fold_addr_expr_loc (loc, core);
     }
   else
diff -pur gcc/gimple-ssa-strength-reduction.c gcc/gimple-ssa-strength-reduction.c
--- gcc/gimple-ssa-strength-reduction.c	2014-04-03 00:07:30.000000000 +0200
+++ gcc/gimple-ssa-strength-reduction.c	2014-04-15 09:39:15.313336522 +0200
@@ -1006,7 +1006,7 @@ slsr_process_ref (gimple gs)
     return;
 
   base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode,
-			      &unsignedp, &volatilep, false);
+			      &unsignedp, &volatilep);
   index = double_int::from_uhwi (bitpos);
 
   if (!restructure_reference (&base, &offset, &index, &type))
diff -pur gcc/simplify-rtx.c gcc/simplify-rtx.c
--- gcc/simplify-rtx.c	2014-01-02 23:23:26.000000000 +0100
+++ gcc/simplify-rtx.c	2014-04-15 09:39:15.349336388 +0200
@@ -296,7 +296,7 @@ delegitimize_mem_from_attrs (rtx x)
 	    int unsignedp, volatilep = 0;
 
 	    decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset,
-					&mode, &unsignedp, &volatilep, false);
+					&mode, &unsignedp, &volatilep);
 	    if (bitsize != GET_MODE_BITSIZE (mode)
 		|| (bitpos % BITS_PER_UNIT)
 		|| (toffset && !tree_fits_shwi_p (toffset)))
diff -pur gcc/tree-affine.c gcc/tree-affine.c
--- gcc/tree-affine.c	2014-01-02 23:23:26.000000000 +0100
+++ gcc/tree-affine.c	2014-04-15 09:39:15.333336448 +0200
@@ -325,8 +325,7 @@ tree_to_aff_combination (tree expr, tree
 	  return;
 	}
       core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
-				  &toffset, &mode, &unsignedp, &volatilep,
-				  false);
+				  &toffset, &mode, &unsignedp, &volatilep);
       if (bitpos % BITS_PER_UNIT != 0)
 	break;
       aff_combination_const (comb, type,
@@ -895,7 +894,7 @@ get_inner_reference_aff (tree ref, aff_t
   int uns, vol;
   aff_tree tmp;
   tree base = get_inner_reference (ref, &bitsize, &bitpos, &toff, &mode,
-				   &uns, &vol, false);
+				   &uns, &vol);
   tree base_addr = build_fold_addr_expr (base);
 
   /* ADDR = &BASE + TOFF + BITPOS / BITS_PER_UNIT.  */
diff -pur gcc/tree-data-ref.c gcc/tree-data-ref.c
--- gcc/tree-data-ref.c	2014-02-04 14:08:00.000000000 +0100
+++ gcc/tree-data-ref.c	2014-04-15 09:39:15.321336493 +0200
@@ -619,7 +619,7 @@ split_constant_offset_1 (tree type, tree
 
 	op0 = TREE_OPERAND (op0, 0);
 	base = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset,
-				    &pmode, &punsignedp, &pvolatilep, false);
+				    &pmode, &punsignedp, &pvolatilep);
 
 	if (pbitpos % BITS_PER_UNIT != 0)
 	  return false;
@@ -769,7 +769,7 @@ dr_analyze_innermost (struct data_refere
     fprintf (dump_file, "analyze_innermost: ");
 
   base = get_inner_reference (ref, &pbitsize, &pbitpos, &poffset,
-			      &pmode, &punsignedp, &pvolatilep, false);
+			      &pmode, &punsignedp, &pvolatilep);
   gcc_assert (base != NULL_TREE);
 
   if (pbitpos % BITS_PER_UNIT != 0)
diff -pur gcc/tree.h gcc/tree.h
--- gcc/tree.h	2014-03-21 12:52:50.000000000 +0100
+++ gcc/tree.h	2014-04-15 09:39:15.169337064 +0200
@@ -4530,8 +4530,7 @@ extern tree build_personality_function (
    look for the ultimate containing object, which is returned and specify
    the access position and size.  */
 extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
-				 tree *, enum machine_mode *, int *, int *,
-				 bool);
+				 tree *, enum machine_mode *, int *, int *);
 
 /* Return a tree representing the lower bound of the array mentioned in
    EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
diff -pur gcc/tree-scalar-evolution.c gcc/tree-scalar-evolution.c
--- gcc/tree-scalar-evolution.c	2014-01-13 20:14:03.000000000 +0100
+++ gcc/tree-scalar-evolution.c	2014-04-15 09:39:15.193336972 +0200
@@ -1733,7 +1733,7 @@ interpret_rhs_expr (struct loop *loop, g
 
 	  base = get_inner_reference (TREE_OPERAND (rhs1, 0),
 				      &bitsize, &bitpos, &offset,
-				      &mode, &unsignedp, &volatilep, false);
+				      &mode, &unsignedp, &volatilep);
 
 	  if (TREE_CODE (base) == MEM_REF)
 	    {
diff -pur gcc/tree-ssa-loop-ivopts.c gcc/tree-ssa-loop-ivopts.c
--- gcc/tree-ssa-loop-ivopts.c	2014-04-07 16:03:55.000000000 +0200
+++ gcc/tree-ssa-loop-ivopts.c	2014-04-15 09:39:15.241336794 +0200
@@ -3776,7 +3776,7 @@ split_address_cost (struct ivopts_data *
   int unsignedp, volatilep;
 
   core = get_inner_reference (addr, &bitsize, &bitpos, &toffset, &mode,
-			      &unsignedp, &volatilep, false);
+			      &unsignedp, &volatilep);
 
   if (toffset != 0
       || bitpos % BITS_PER_UNIT != 0
diff -pur gcc/tree-vect-data-refs.c gcc/tree-vect-data-refs.c
--- gcc/tree-vect-data-refs.c	2014-02-21 14:18:54.000000000 +0100
+++ gcc/tree-vect-data-refs.c	2014-04-15 09:40:47.068991277 +0200
@@ -2990,7 +2990,7 @@ vect_check_gather (gimple stmt, loop_vec
      SSA_NAME OFF and put the loop invariants into a tree BASE
      that can be gimplified before the loop.  */
   base = get_inner_reference (base, &pbitsize, &pbitpos, &off,
-			      &pmode, &punsignedp, &pvolatilep, false);
+			      &pmode, &punsignedp, &pvolatilep);
   gcc_assert (base != NULL_TREE && (pbitpos % BITS_PER_UNIT) == 0);
 
   if (TREE_CODE (base) == MEM_REF)
@@ -3543,7 +3543,7 @@ again:
 	    }
 
 	  outer_base = get_inner_reference (inner_base, &pbitsize, &pbitpos,
-		          &poffset, &pmode, &punsignedp, &pvolatilep, false);
+		          &poffset, &pmode, &punsignedp, &pvolatilep);
 	  gcc_assert (outer_base != NULL_TREE);
 
 	  if (pbitpos % BITS_PER_UNIT != 0)
diff -pur gcc/tsan.c gcc/tsan.c
--- gcc/tsan.c	2014-01-08 10:06:27.000000000 +0100
+++ gcc/tsan.c	2014-04-15 09:39:15.293336598 +0200
@@ -121,7 +121,7 @@ instrument_expr (gimple_stmt_iterator gs
   enum machine_mode mode;
   int volatilep = 0, unsignedp = 0;
   base = get_inner_reference (expr, &bitsize, &bitpos, &offset,
-			      &mode, &unsignedp, &volatilep, false);
+			      &mode, &unsignedp, &volatilep);
 
   /* No need to instrument accesses to decls that don't escape,
      they can't escape to other threads then.  */
diff -pur gcc/ubsan.c gcc/ubsan.c
--- gcc/ubsan.c	2014-03-26 20:33:40.000000000 +0100
+++ gcc/ubsan.c	2014-04-15 09:55:40.357745684 +0200
@@ -797,7 +797,7 @@ instrument_bool_enum_load (gimple_stmt_i
   enum machine_mode mode;
   int volatilep = 0, unsignedp = 0;
   tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
-				   &unsignedp, &volatilep, false);
+				   &unsignedp, &volatilep);
   tree utype = build_nonstandard_integer_type (modebitsize, 1);
 
   if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2014-04-22  7:55                                                                                 ` Bernd Edlinger
@ 2014-04-22  8:11                                                                                   ` Eric Botcazou
  2014-04-22  8:33                                                                                     ` Bernd Edlinger
  0 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2014-04-22  8:11 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek

> I still have that already-approved patch, updated to current trunk.
> I've successfully boot-strapped it on armv7-linux-gnueabihf with
> all languages enabled, including Ada.
> The test suite runs cleanly without any drop-outs.

Thanks for the testing.

> Is it OK to commit now, or are there objections?

I think that the patch is either incomplete or wrong, in the sense that it 
will break TYPE_ALIGN_OK support, unless this support is totally obsolete, in 
which case it ought to be totally removed instead of just partially.  The Ada 
testsuite in the compiler isn't exhaustive enough to give any guarantee so I 
will need to conduct more testing.  Can you sit on the patch a few weeks?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH] Remove "keep_aligning" from get_inner_reference
  2014-04-22  8:11                                                                                   ` Eric Botcazou
@ 2014-04-22  8:33                                                                                     ` Bernd Edlinger
  2014-04-22  9:36                                                                                       ` Eric Botcazou
  0 siblings, 1 reply; 105+ messages in thread
From: Bernd Edlinger @ 2014-04-22  8:33 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek

Hi Eric,

On Tue, 22 Apr 2014 10:09:28, Eric Botcazou wrote:
>
>> I still have that already-approved patch, updated to current trunk.
>> I've successfully boot-strapped it on armv7-linux-gnueabihf with
>> all languages enabled, including Ada.
>> The test suite runs cleanly without any drop-outs.
>
> Thanks for the testing.
>
>> Is it OK to commit now, or are there objections?
>
> I think that the patch is either incomplete or wrong, in the sense that it
> will break TYPE_ALIGN_OK support, unless this support is totally obsolete, in
> which case it ought to be totally removed instead of just partially. The Ada
> testsuite in the compiler isn't exhaustive enough to give any guarantee so I
> will need to conduct more testing. Can you sit on the patch a few weeks?
>

Sure, and thanks again for your help.

I was not able to find any difference on the generated code with
or without that patch.


Bernd.

> --
> Eric Botcazou
 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2014-04-22  8:33                                                                                     ` Bernd Edlinger
@ 2014-04-22  9:36                                                                                       ` Eric Botcazou
  2014-05-02  6:18                                                                                         ` Jeff Law
  0 siblings, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2014-04-22  9:36 UTC (permalink / raw)
  To: Bernd Edlinger; +Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek

> Sure, and thanks again for your help.

Thanks!

> I was not able to find any difference on the generated code with
> or without that patch.

Yes, my gut feeling is that TYPE_ALIGN_OK is really obsolete now.  It is set 
in a single place in the compiler (gcc-interface/decl.c:gnat_to_gnu_entity):

      /* Tell the middle-end that objects of tagged types are guaranteed to
	 be properly aligned.  This is necessary because conversions to the
	 class-wide type are translated into conversions to the root type,
	 which can be less aligned than some of its derived types.  */
      if (Is_Tagged_Type (gnat_entity)
	  || Is_Class_Wide_Equivalent_Type (gnat_entity))
	TYPE_ALIGN_OK (gnu_type) = 1;

but we changed the way these conversions are done some time ago.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2014-04-22  9:36                                                                                       ` Eric Botcazou
@ 2014-05-02  6:18                                                                                         ` Jeff Law
  2014-05-05  8:00                                                                                           ` Richard Biener
  0 siblings, 1 reply; 105+ messages in thread
From: Jeff Law @ 2014-05-02  6:18 UTC (permalink / raw)
  To: Eric Botcazou, Bernd Edlinger
  Cc: gcc-patches, Richard Biener, Martin Jambor, Jakub Jelinek

On 04/22/14 03:25, Eric Botcazou wrote:
>> Sure, and thanks again for your help.
>
> Thanks!
>
>> I was not able to find any difference on the generated code with
>> or without that patch.
>
> Yes, my gut feeling is that TYPE_ALIGN_OK is really obsolete now.  It is set
> in a single place in the compiler (gcc-interface/decl.c:gnat_to_gnu_entity):
>
>        /* Tell the middle-end that objects of tagged types are guaranteed to
> 	 be properly aligned.  This is necessary because conversions to the
> 	 class-wide type are translated into conversions to the root type,
> 	 which can be less aligned than some of its derived types.  */
>        if (Is_Tagged_Type (gnat_entity)
> 	  || Is_Class_Wide_Equivalent_Type (gnat_entity))
> 	TYPE_ALIGN_OK (gnu_type) = 1;
>
> but we changed the way these conversions are done some time ago.
So does this remove the last concern around Bernd's patch?

Jeff

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2014-05-02  6:18                                                                                         ` Jeff Law
@ 2014-05-05  8:00                                                                                           ` Richard Biener
  2014-05-05 20:25                                                                                             ` Mike Stump
  2014-05-14  7:30                                                                                             ` Eric Botcazou
  0 siblings, 2 replies; 105+ messages in thread
From: Richard Biener @ 2014-05-05  8:00 UTC (permalink / raw)
  To: Jeff Law
  Cc: Eric Botcazou, Bernd Edlinger, GCC Patches, Martin Jambor, Jakub Jelinek

On Fri, May 2, 2014 at 8:18 AM, Jeff Law <law@redhat.com> wrote:
> On 04/22/14 03:25, Eric Botcazou wrote:
>>>
>>> Sure, and thanks again for your help.
>>
>>
>> Thanks!
>>
>>> I was not able to find any difference on the generated code with
>>> or without that patch.
>>
>>
>> Yes, my gut feeling is that TYPE_ALIGN_OK is really obsolete now.  It is
>> set
>> in a single place in the compiler
>> (gcc-interface/decl.c:gnat_to_gnu_entity):
>>
>>        /* Tell the middle-end that objects of tagged types are guaranteed
>> to
>>          be properly aligned.  This is necessary because conversions to
>> the
>>          class-wide type are translated into conversions to the root type,
>>          which can be less aligned than some of its derived types.  */
>>        if (Is_Tagged_Type (gnat_entity)
>>           || Is_Class_Wide_Equivalent_Type (gnat_entity))
>>         TYPE_ALIGN_OK (gnu_type) = 1;
>>
>> but we changed the way these conversions are done some time ago.
>
> So does this remove the last concern around Bernd's patch?

And can we remove TYPE_ALIGN_OK as followup?  (ISTR it's used
by obj-c/c++ as well, but I can't find such use)

Thanks,
Richard.

> Jeff
>

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2014-05-05  8:00                                                                                           ` Richard Biener
@ 2014-05-05 20:25                                                                                             ` Mike Stump
  2014-05-14  7:30                                                                                             ` Eric Botcazou
  1 sibling, 0 replies; 105+ messages in thread
From: Mike Stump @ 2014-05-05 20:25 UTC (permalink / raw)
  To: Richard Biener
  Cc: Jeff Law, Eric Botcazou, Bernd Edlinger, GCC Patches,
	Martin Jambor, Jakub Jelinek

On May 5, 2014, at 1:00 AM, Richard Biener <richard.guenther@gmail.com> wrote:
> And can we remove TYPE_ALIGN_OK as followup?  (ISTR it's used
> by obj-c/c++ as well, but I can't find such use)

I didn’t find any current hint…  the only landmine I found was:

./gcc/config/pa/pa.c:1878:                    /* Using TYPE_ALIGN_OK is rather conservative as
./gcc/config/pa/pa.c:1880:                    align = (TYPE_ALIGN_OK (type) ? TYPE_ALIGN (type)

^ permalink raw reply	[flat|nested] 105+ messages in thread

* Re: [PATCH] Remove "keep_aligning" from get_inner_reference
  2014-05-05  8:00                                                                                           ` Richard Biener
  2014-05-05 20:25                                                                                             ` Mike Stump
@ 2014-05-14  7:30                                                                                             ` Eric Botcazou
  2014-05-14  9:06                                                                                               ` Bernd Edlinger
  1 sibling, 1 reply; 105+ messages in thread
From: Eric Botcazou @ 2014-05-14  7:30 UTC (permalink / raw)
  To: Richard Biener
  Cc: gcc-patches, Jeff Law, Bernd Edlinger, Martin Jambor, Jakub Jelinek

> > So does this remove the last concern around Bernd's patch?
> 
> And can we remove TYPE_ALIGN_OK as followup?  (ISTR it's used
> by obj-c/c++ as well, but I can't find such use)

Probably but, as previously indicated, I need to do some testing first.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 105+ messages in thread

* RE: [PATCH] Remove "keep_aligning" from get_inner_reference
  2014-05-14  7:30                                                                                             ` Eric Botcazou
@ 2014-05-14  9:06                                                                                               ` Bernd Edlinger
  0 siblings, 0 replies; 105+ messages in thread
From: Bernd Edlinger @ 2014-05-14  9:06 UTC (permalink / raw)
  To: Eric Botcazou, Richard Biener
  Cc: gcc-patches, Jeff Law, Martin Jambor, Jakub Jelinek

Hi Eric,

On Wed, 14 May 2014 09:28:55, Eric Botcazou wrote:
>
>>> So does this remove the last concern around Bernd's patch?
>>
>> And can we remove TYPE_ALIGN_OK as followup? (ISTR it's used
>> by obj-c/c++ as well, but I can't find such use)
>
> Probably but, as previously indicated, I need to do some testing first.
>
> --
> Eric Botcazou

Ok sure, I'll be patient...


If I remove this line, the build fails:

gcc-interface/decl.c:gnat_to_gnu_entity:
 
      /* Tell the middle-end that objects of tagged types are guaranteed to
	 be properly aligned.  This is necessary because conversions to the
	 class-wide type are translated into conversions to the root type,
	 which can be less aligned than some of its derived types.  */
      if (Is_Tagged_Type (gnat_entity)
	  || Is_Class_Wide_Equivalent_Type (gnat_entity))
	TYPE_ALIGN_OK (gnu_type) = 1;
 
but only because this bit is read back in the ada/gcc-interface.

If I apply my patch, and additionally remove this line in expr.c,
which is  one of the last references to TYPE_ALIGN_OK in the middle-end:

          if (TYPE_ALIGN_OK (type))
            {
              /* ??? Copying the MEM without substantially changing it might
                 run afoul of the code handling volatile memory references in
                 store_expr, which assumes that TARGET is returned unmodified
                 if it has been used.  */
              op0 = copy_rtx (op0);
              set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
            }

nothing changes. All test cases pass, and again I can not see any difference in the
generated code (I compare gcc/ada/*.o with and without patch).

So, currently I am under the impression that TYPE_ALIGN_OK has some relevance
to the Ada front-end, but it should not be used in the middle-end and certainly not
in the back-end.


Bernd.
 		 	   		  

^ permalink raw reply	[flat|nested] 105+ messages in thread

end of thread, other threads:[~2014-05-14  9:06 UTC | newest]

Thread overview: 105+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-06  7:03 [PATCH, PR 57748] Check for out of bounds access Bernd Edlinger
2013-09-06  7:31 ` Richard Biener
     [not found]   ` <DUB122-W323D4AAAEA1AFA890BF243E43C0@phx.gbl>
     [not found]     ` <CAFiYyc13wC0jmZ4xELAiL5L5Sbh0yauZWViP2hTdR+H4s0iPSw@mail.gmail.com>
     [not found]       ` <DUB122-W4D571A91831593BA22438E43C0@phx.gbl>
2013-09-06  9:19         ` Richard Biener
2013-09-06  9:30           ` Bernd Edlinger
2013-09-10 21:33           ` Martin Jambor
2013-09-11 14:42             ` Bernd Edlinger
2013-09-11 14:47               ` Richard Biener
2013-09-12 21:07                 ` Bernd Edlinger
2013-09-13  9:37                   ` Eric Botcazou
2013-09-13  9:48                     ` Bernd Edlinger
2013-09-15 19:08                 ` Bernd Edlinger
2013-09-17  0:05                   ` Martin Jambor
2013-09-17 10:32                     ` Bernd Edlinger
2013-10-22 14:08                     ` Bernd Edlinger
2013-10-23 16:02                       ` Richard Biener
2013-10-24  0:09                         ` Bernd Edlinger
2013-10-24  8:44                         ` Eric Botcazou
2013-10-24 10:06                           ` Richard Biener
2013-10-24 10:22                             ` Bernd Edlinger
2013-10-25 10:40                             ` Eric Botcazou
2013-11-06 15:08                       ` [PATCH, PR 57748] Check for out of bounds access, Part 3 Bernd Edlinger
2013-12-03 13:27                         ` [PE-POST] Adjust Bit-region in expand_assignment Bernd Edlinger
2013-12-04  5:55                           ` Jeff Law
2013-12-04  7:50                             ` Bernd Edlinger
2013-12-06  4:13                               ` Jeff Law
2013-12-06  8:03                                 ` Bernd Edlinger
2013-12-06  9:49                                   ` Richard Biener
2013-09-17 11:07                   ` [PATCH, PR 57748] Check for out of bounds access Richard Biener
2013-09-17 11:41                     ` Richard Biener
2013-09-17 12:48                       ` Bernd Edlinger
2013-09-24 11:40                         ` Richard Biener
2013-09-24 11:56                           ` Bernd Edlinger
2013-09-24  6:34                       ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger
2013-09-24 10:31                         ` Richard Biener
2013-09-24 14:46                           ` Eric Botcazou
2013-09-24 18:51                           ` Martin Jambor
2013-09-25  9:51                             ` Richard Biener
2013-09-25 14:56                               ` Martin Jambor
2013-09-26  9:34                                 ` Bernd Edlinger
2013-09-26 11:18                                   ` Eric Botcazou
2013-09-26 12:42                                     ` Bernd Edlinger
2013-09-27  8:45                                       ` Eric Botcazou
2013-10-03  0:37                                         ` Bernd Edlinger
2013-10-08  8:02                                           ` Eric Botcazou
2013-10-08  9:22                                             ` Bernd Edlinger
2013-10-08 21:04                                               ` Eric Botcazou
2013-10-08 23:03                                                 ` Bernd Edlinger
2013-10-11 17:27                                                   ` Eric Botcazou
2013-10-13  8:22                                                     ` Bernd Edlinger
2013-10-13 12:29                                                       ` Eric Botcazou
2013-10-13 12:30                                                         ` Bernd Edlinger
2013-10-13 14:06                                                           ` Eric Botcazou
2013-10-22 11:02                                                   ` Bernd Edlinger
2013-10-23 16:14                                                     ` Richard Biener
2013-10-23 17:25                                                       ` Martin Jambor
2013-10-23 18:05                                                         ` Eric Botcazou
2013-10-24  8:20                                                         ` Bernd Edlinger
2013-10-24  9:16                                                           ` Eric Botcazou
2013-10-24 10:00                                                             ` Bernd Edlinger
2013-10-24 10:16                                                               ` Eric Botcazou
2013-10-24 10:50                                                             ` Richard Biener
2013-10-24 13:09                                                               ` Bernd Edlinger
2013-10-24 13:16                                                                 ` Richard Biener
2013-10-24 13:38                                                                   ` Bernd Edlinger
2013-10-25  7:05                                                                   ` Bernd Edlinger
2013-10-25  9:29                                                                     ` Richard Biener
2013-10-25 10:40                                                                       ` Bernd Edlinger
2013-10-25 11:10                                                                         ` Richard Biener
2013-10-25 14:01                                                                           ` Martin Jambor
2013-10-27 20:21                                                                           ` [PATCH] Remove "keep_aligning" from get_inner_reference Bernd Edlinger
2013-11-26 12:37                                                                             ` Richard Biener
2013-11-27 11:28                                                                             ` Eric Botcazou
2013-11-27 12:24                                                                               ` Bernd Edlinger
2013-11-27 12:33                                                                                 ` Eric Botcazou
2013-11-27 13:30                                                                               ` Richard Biener
2013-11-27 15:10                                                                                 ` Bernd Edlinger
2013-11-27 16:25                                                                                 ` Eric Botcazou
2013-11-27 16:33                                                                                   ` Richard Biener
2013-11-27 16:43                                                                                     ` Eric Botcazou
2014-04-22  7:55                                                                                 ` Bernd Edlinger
2014-04-22  8:11                                                                                   ` Eric Botcazou
2014-04-22  8:33                                                                                     ` Bernd Edlinger
2014-04-22  9:36                                                                                       ` Eric Botcazou
2014-05-02  6:18                                                                                         ` Jeff Law
2014-05-05  8:00                                                                                           ` Richard Biener
2014-05-05 20:25                                                                                             ` Mike Stump
2014-05-14  7:30                                                                                             ` Eric Botcazou
2014-05-14  9:06                                                                                               ` Bernd Edlinger
2013-11-07 13:23                                                                           ` [PATCH, PR 57748] Check for out of bounds access, Part 2 Bernd Edlinger
2013-11-07 13:23                                                                             ` Bernd Edlinger
2013-11-19 15:05                                                                               ` Bernd Edlinger
2013-11-27 16:22                                                                                 ` [PING] " Bernd Edlinger
2013-11-27 17:09                                                                                   ` Richard Biener
2013-11-27 22:30                                                                                   ` Jeff Law
2013-11-28 12:36                                                                                     ` Bernd Edlinger
2013-12-03  6:00                                                                                       ` Jeff Law
2013-10-24 13:20                                                                 ` Jakub Jelinek
2013-10-24 13:42                                                                   ` Richard Biener
2013-10-24 11:14                                                           ` Richard Biener
2013-10-24 13:13                                                             ` Richard Biener
2013-10-23 17:45                                                       ` Eric Botcazou
2013-09-25 13:22                             ` Bernd Edlinger
2013-09-06  9:29 ` [PATCH, PR 57748] Check for out of bounds access Eric Botcazou
2013-09-06  9:30   ` Jakub Jelinek
2013-09-06 10:30     ` Bernd Edlinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).