public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* gcc miscompiling duff's device (probaby two different bugs)
@ 2010-03-02  9:38 Peter Kourzanov
  2010-03-02 10:24 ` Andrew Haley
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Peter Kourzanov @ 2010-03-02  9:38 UTC (permalink / raw)
  To: gcc

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


Hi guys,

  I have the following variation on Duff's device that seems to 
mis-compile on all GCC versions I can access within a minute (that 
is gcc-3.{3,4}, gcc-4.{1,2,3,4} on x86 and gcc-4.3.2 on x86_64). The 
symptoms are as follows:

$ gcc-4.4 -o duffbug duffbug.c ; ./duffbug
{ he��3)
{ hello world ! }

  As you can observe in the difference between duff4_works() and 
duff4_fails(), apparently due to for-loop initializer being externalized
vs. specified as the first for-loop expression. It doesn't matter if the
'case 0' is  labeling the for-loop, or the first statement in the 
for-loop in case of duff4_works() of course. However, older gcc-3.x do
give a warning though if the 'case 0' labels the first statement for 
duff4_fails(), since the first expression in the for-loop is then
inaccessible. All gcc-4.x versions don't warn, even when supplied with
the -Wall flag (which is wrong, hence this *first* bug):

$ gcc-4.4 -Wall -o duffbug duffbug.c ; ./duffbug
$ gcc-3.4 -Wall -o duffbug duffbug.c ; ./duffbug
duffbug.c: In function `duff4_fails':
duffbug.c:28: warning: unreachable code at beginning of switch statement

  I think the compiler is generating wrong code for duff4_fails() when
'case 0' labels the for-loop. It somehow skips the first for-loop
expression, just as if 'case 0' pointed to the first statement in the
for-loop (hence this *second* bug). Haven't checked the assembly
though...

Kind regards,

Pjotr Kourzanov

[-- Attachment #2: duffbug.c --]
[-- Type: text/x-csrc, Size: 1117 bytes --]

#include <stdio.h>

int duff4_works(char * dst,const char * src,const size_t n)
{
  const size_t rem=n % 4, a=rem + (!rem)*4;
  char * d=dst+=a;
  const char * s=src+=a;
  dst+=n;
  
    switch (rem) {
    case 0:  for(/* gcc bug? dst+=n*/;d<dst;d+=4,s+=4) {
    /*case 0:*/	d[-4]=s[-4];
    case 3:	d[-3]=s[-3];
    case 2:	d[-2]=s[-2];
    case 1:	d[-1]=s[-1];
	      }
    }
	return 0;
}
int duff4_fails(char * dst,const char * src,const size_t n)
{
  const size_t rem=n % 4, a=rem + (!rem)*4;
  char * d=dst+=a;
  const char * s=src+=a;
  /* gcc bug? dst+=n; */
  
    switch (rem) {
    case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
    /*case 0:*/	d[-4]=s[-4];
    case 3:	d[-3]=s[-3];
    case 2:	d[-2]=s[-2];
    case 1:	d[-1]=s[-1];
	      }
    }
	return 0;
}
int main()
{
    char s[]="< hello world ! >";
    {
	char d[sizeof(s)];

	d[0]='{';
	d[sizeof(s)-2]='}';
	duff4_fails(&d[1],&s[1],sizeof(s)-3);
	d[sizeof(s)-1]='\0';
	printf("%s\n",d);
    }
    {
	char d[sizeof(s)];

	d[0]='{';
	d[sizeof(s)-2]='}';
	duff4_works(&d[1],&s[1],sizeof(s)-3);
	d[sizeof(s)-1]='\0';
	printf("%s\n",d);
    }

    return 0;
}

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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02  9:38 gcc miscompiling duff's device (probaby two different bugs) Peter Kourzanov
@ 2010-03-02 10:24 ` Andrew Haley
  2010-03-02 10:34   ` Pjotr Kourzanov
  2010-03-02 10:27 ` Richard Guenther
  2010-03-02 10:58 ` Andreas Schwab
  2 siblings, 1 reply; 11+ messages in thread
From: Andrew Haley @ 2010-03-02 10:24 UTC (permalink / raw)
  To: gcc

On 03/02/2010 09:38 AM, Peter Kourzanov wrote:

>   I have the following variation on Duff's device that seems to 
> mis-compile on all GCC versions I can access within a minute (that 
> is gcc-3.{3,4}, gcc-4.{1,2,3,4} on x86 and gcc-4.3.2 on x86_64). The 
> symptoms are as follows:
> 
> $ gcc-4.4 -o duffbug duffbug.c ; ./duffbug
> { he��3)
> { hello world ! }
> 
>   As you can observe in the difference between duff4_works() and 
> duff4_fails(), apparently due to for-loop initializer being externalized
> vs. specified as the first for-loop expression. It doesn't matter if the
> 'case 0' is  labeling the for-loop, or the first statement in the 
> for-loop in case of duff4_works() of course. However, older gcc-3.x do
> give a warning though if the 'case 0' labels the first statement for 
> duff4_fails(), since the first expression in the for-loop is then
> inaccessible. All gcc-4.x versions don't warn, even when supplied with
> the -Wall flag (which is wrong, hence this *first* bug):

So, your claim is that gcc should warn about the for loop initializer
being unreachable.  is that correct?

> $ gcc-4.4 -Wall -o duffbug duffbug.c ; ./duffbug
> $ gcc-3.4 -Wall -o duffbug duffbug.c ; ./duffbug
> duffbug.c: In function `duff4_fails':
> duffbug.c:28: warning: unreachable code at beginning of switch statement
> 
>   I think the compiler is generating wrong code for duff4_fails() when
> 'case 0' labels the for-loop. It somehow skips the first for-loop
> expression, just as if 'case 0' pointed to the first statement in the
> for-loop (hence this *second* bug). Haven't checked the assembly
> though...

I don't understand.  In what way is the code gcc generates wrong?

int duff4_fails(char * dst,const char * src,const size_t n)
{
  const size_t rem=n % 4, a=rem + (!rem)*4;
  char * d=dst+=a;
  const char * s=src+=a;
  /* gcc bug? dst+=n; */
  
    switch (rem) {
    case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
    /*case 0:*/	d[-4]=s[-4];
    case 3:	d[-3]=s[-3];
    case 2:	d[-2]=s[-2];
    case 1:	d[-1]=s[-1];
	      }
    }
	return 0;
}
The first time around the loop the initializer (d+=n) is jumped around, so
d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
exits.

Andrew.

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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02  9:38 gcc miscompiling duff's device (probaby two different bugs) Peter Kourzanov
  2010-03-02 10:24 ` Andrew Haley
@ 2010-03-02 10:27 ` Richard Guenther
  2010-03-02 10:39   ` Pjotr Kourzanov
  2010-03-02 10:58 ` Andreas Schwab
  2 siblings, 1 reply; 11+ messages in thread
From: Richard Guenther @ 2010-03-02 10:27 UTC (permalink / raw)
  To: Peter Kourzanov; +Cc: gcc

On Tue, Mar 2, 2010 at 10:38 AM, Peter Kourzanov
<peter.kourzanov@gmail.com> wrote:
>
> Hi guys,
>
>  I have the following variation on Duff's device that seems to
> mis-compile on all GCC versions I can access within a minute (that
> is gcc-3.{3,4}, gcc-4.{1,2,3,4} on x86 and gcc-4.3.2 on x86_64). The
> symptoms are as follows:
>
> $ gcc-4.4 -o duffbug duffbug.c ; ./duffbug
> { he��3)
> { hello world ! }
>
>  As you can observe in the difference between duff4_works() and
> duff4_fails(), apparently due to for-loop initializer being externalized
> vs. specified as the first for-loop expression. It doesn't matter if the
> 'case 0' is  labeling the for-loop, or the first statement in the
> for-loop in case of duff4_works() of course. However, older gcc-3.x do
> give a warning though if the 'case 0' labels the first statement for
> duff4_fails(), since the first expression in the for-loop is then
> inaccessible. All gcc-4.x versions don't warn, even when supplied with
> the -Wall flag (which is wrong, hence this *first* bug):
>
> $ gcc-4.4 -Wall -o duffbug duffbug.c ; ./duffbug
> $ gcc-3.4 -Wall -o duffbug duffbug.c ; ./duffbug
> duffbug.c: In function `duff4_fails':
> duffbug.c:28: warning: unreachable code at beginning of switch statement
>
>  I think the compiler is generating wrong code for duff4_fails() when
> 'case 0' labels the for-loop. It somehow skips the first for-loop
> expression, just as if 'case 0' pointed to the first statement in the
> for-loop (hence this *second* bug). Haven't checked the assembly
> though...

The routines are not equivalent.  in _works you unconditionally
do dst += n while in _fails you only do it for rem == 0.

Richard.

> Kind regards,
>
> Pjotr Kourzanov
>

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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02 10:24 ` Andrew Haley
@ 2010-03-02 10:34   ` Pjotr Kourzanov
  2010-03-02 10:47     ` Andrew Haley
  0 siblings, 1 reply; 11+ messages in thread
From: Pjotr Kourzanov @ 2010-03-02 10:34 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc

On Tue, 2010-03-02 at 10:24 +0000, Andrew Haley wrote: 
> On 03/02/2010 09:38 AM, Peter Kourzanov wrote:
> 
> >   I have the following variation on Duff's device that seems to 
> > mis-compile on all GCC versions I can access within a minute (that 
> > is gcc-3.{3,4}, gcc-4.{1,2,3,4} on x86 and gcc-4.3.2 on x86_64). The 
> > symptoms are as follows:
> > 
> > $ gcc-4.4 -o duffbug duffbug.c ; ./duffbug
> > { he��3)
> > { hello world ! }
> > 
> >   As you can observe in the difference between duff4_works() and 
> > duff4_fails(), apparently due to for-loop initializer being externalized
> > vs. specified as the first for-loop expression. It doesn't matter if the
> > 'case 0' is  labeling the for-loop, or the first statement in the 
> > for-loop in case of duff4_works() of course. However, older gcc-3.x do
> > give a warning though if the 'case 0' labels the first statement for 
> > duff4_fails(), since the first expression in the for-loop is then
> > inaccessible. All gcc-4.x versions don't warn, even when supplied with
> > the -Wall flag (which is wrong, hence this *first* bug):
> 
> So, your claim is that gcc should warn about the for loop initializer
> being unreachable.  is that correct?

Exactly. Just like what gcc-3.x does, even without the -Wall flag.

> 
> > $ gcc-4.4 -Wall -o duffbug duffbug.c ; ./duffbug
> > $ gcc-3.4 -Wall -o duffbug duffbug.c ; ./duffbug
> > duffbug.c: In function `duff4_fails':
> > duffbug.c:28: warning: unreachable code at beginning of switch statement
> > 
> >   I think the compiler is generating wrong code for duff4_fails() when
> > 'case 0' labels the for-loop. It somehow skips the first for-loop
> > expression, just as if 'case 0' pointed to the first statement in the
> > for-loop (hence this *second* bug). Haven't checked the assembly
> > though...
> 
> I don't understand.  In what way is the code gcc generates wrong?
> 
> int duff4_fails(char * dst,const char * src,const size_t n)
> {
>   const size_t rem=n % 4, a=rem + (!rem)*4;
>   char * d=dst+=a;
>   const char * s=src+=a;
>   /* gcc bug? dst+=n; */
>   
>     switch (rem) {
>     case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
>     /*case 0:*/	d[-4]=s[-4];
>     case 3:	d[-3]=s[-3];
>     case 2:	d[-2]=s[-2];
>     case 1:	d[-1]=s[-1];
> 	      }
>     }
> 	return 0;
> }
> The first time around the loop the initializer (d+=n) is jumped around, so
> d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
> exits.

  And its wrong since it shouldn't jump around the initializer.  The
following two snippets exhibit the same behaviour:

> case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
> /*case 0:*/	d[-4]=s[-4];

> /*case 0:*/  for(dst+=n;d<dst;d+=4,s+=4)  {
> case 0:	d[-4]=s[-4];

  Which is wrong IMHO.

Kind regards,

Pjotr

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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02 10:27 ` Richard Guenther
@ 2010-03-02 10:39   ` Pjotr Kourzanov
  0 siblings, 0 replies; 11+ messages in thread
From: Pjotr Kourzanov @ 2010-03-02 10:39 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc

On Tue, 2010-03-02 at 11:27 +0100, Richard Guenther wrote: 
> On Tue, Mar 2, 2010 at 10:38 AM, Peter Kourzanov
> <peter.kourzanov@gmail.com> wrote:
> >
> > Hi guys,
> >
> >  I have the following variation on Duff's device that seems to
> > mis-compile on all GCC versions I can access within a minute (that
> > is gcc-3.{3,4}, gcc-4.{1,2,3,4} on x86 and gcc-4.3.2 on x86_64). The
> > symptoms are as follows:
> >
> > $ gcc-4.4 -o duffbug duffbug.c ; ./duffbug
> > { he��3)
> > { hello world ! }
> >
> >  As you can observe in the difference between duff4_works() and
> > duff4_fails(), apparently due to for-loop initializer being externalized
> > vs. specified as the first for-loop expression. It doesn't matter if the
> > 'case 0' is  labeling the for-loop, or the first statement in the
> > for-loop in case of duff4_works() of course. However, older gcc-3.x do
> > give a warning though if the 'case 0' labels the first statement for
> > duff4_fails(), since the first expression in the for-loop is then
> > inaccessible. All gcc-4.x versions don't warn, even when supplied with
> > the -Wall flag (which is wrong, hence this *first* bug):
> >
> > $ gcc-4.4 -Wall -o duffbug duffbug.c ; ./duffbug
> > $ gcc-3.4 -Wall -o duffbug duffbug.c ; ./duffbug
> > duffbug.c: In function `duff4_fails':
> > duffbug.c:28: warning: unreachable code at beginning of switch statement
> >
> >  I think the compiler is generating wrong code for duff4_fails() when
> > 'case 0' labels the for-loop. It somehow skips the first for-loop
> > expression, just as if 'case 0' pointed to the first statement in the
> > for-loop (hence this *second* bug). Haven't checked the assembly
> > though...
> 
> The routines are not equivalent.  in _works you unconditionally
> do dst += n while in _fails you only do it for rem == 0.

That's right. And about missing warning?

> 
> Richard.
> 
> > Kind regards,
> >
> > Pjotr Kourzanov
> >
> 


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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02 10:34   ` Pjotr Kourzanov
@ 2010-03-02 10:47     ` Andrew Haley
  2010-03-02 11:00       ` Pjotr Kourzanov
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Haley @ 2010-03-02 10:47 UTC (permalink / raw)
  To: gcc

On 03/02/2010 10:34 AM, Pjotr Kourzanov wrote:

>> int duff4_fails(char * dst,const char * src,const size_t n)
>> {
>>   const size_t rem=n % 4, a=rem + (!rem)*4;
>>   char * d=dst+=a;
>>   const char * s=src+=a;
>>   /* gcc bug? dst+=n; */
>>   
>>     switch (rem) {
>>     case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
>>     /*case 0:*/	d[-4]=s[-4];
>>     case 3:	d[-3]=s[-3];
>>     case 2:	d[-2]=s[-2];
>>     case 1:	d[-1]=s[-1];
>> 	      }
>>     }
>> 	return 0;
>> }
>> The first time around the loop the initializer (d+=n) is jumped around, so
>> d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
>> exits.
> 
>   And its wrong since it shouldn't jump around the initializer.

Sure it should.  On entry to that loop, rem == 3.

Andrew.

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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02  9:38 gcc miscompiling duff's device (probaby two different bugs) Peter Kourzanov
  2010-03-02 10:24 ` Andrew Haley
  2010-03-02 10:27 ` Richard Guenther
@ 2010-03-02 10:58 ` Andreas Schwab
  2 siblings, 0 replies; 11+ messages in thread
From: Andreas Schwab @ 2010-03-02 10:58 UTC (permalink / raw)
  To: Peter Kourzanov; +Cc: gcc

Peter Kourzanov <peter.kourzanov@gmail.com> writes:

>   I think the compiler is generating wrong code for duff4_fails() when
> 'case 0' labels the for-loop. It somehow skips the first for-loop
> expression,

If rem != 0 you jump over the init expression, so it is never executed.

Andreas.

-- 
Andreas Schwab, schwab@redhat.com
GPG Key fingerprint = D4E8 DBE3 3813 BB5D FA84  5EC7 45C6 250E 6F00 984E
"And now for something completely different."

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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02 10:47     ` Andrew Haley
@ 2010-03-02 11:00       ` Pjotr Kourzanov
  2010-03-02 11:26         ` Richard Guenther
  0 siblings, 1 reply; 11+ messages in thread
From: Pjotr Kourzanov @ 2010-03-02 11:00 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc

On Tue, 2010-03-02 at 10:47 +0000, Andrew Haley wrote: 
> On 03/02/2010 10:34 AM, Pjotr Kourzanov wrote:
> 
> >> int duff4_fails(char * dst,const char * src,const size_t n)
> >> {
> >>   const size_t rem=n % 4, a=rem + (!rem)*4;
> >>   char * d=dst+=a;
> >>   const char * s=src+=a;
> >>   /* gcc bug? dst+=n; */
> >>   
> >>     switch (rem) {
> >>     case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
> >>     /*case 0:*/	d[-4]=s[-4];
> >>     case 3:	d[-3]=s[-3];
> >>     case 2:	d[-2]=s[-2];
> >>     case 1:	d[-1]=s[-1];
> >> 	      }
> >>     }
> >> 	return 0;
> >> }
> >> The first time around the loop the initializer (d+=n) is jumped around, so
> >> d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
> >> exits.
> > 
> >   And its wrong since it shouldn't jump around the initializer.
> 
> Sure it should.  On entry to that loop, rem == 3.

  I agree, this is one of the places where referential transparency
breaks in C. I wouldn't have expected that the compiler could or 
would put the first expression before the switch in this case:

switch (rem) {
  for(dst+=n;d<dst;d+=4,s+=4) { 
case 0:	d[-4]=s[-4]; ...
}}

However, the warning is still due, since a combination of a switch with a
for loop results in code that is completely ignored, i.e., is inaccessible. 
As I said, gcc-3.x used to issue a warning for this one...

> 
> Andrew.
> 


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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02 11:00       ` Pjotr Kourzanov
@ 2010-03-02 11:26         ` Richard Guenther
  2010-03-02 13:07           ` Peter Kourzanov
  0 siblings, 1 reply; 11+ messages in thread
From: Richard Guenther @ 2010-03-02 11:26 UTC (permalink / raw)
  To: Pjotr Kourzanov; +Cc: Andrew Haley, gcc

On Tue, Mar 2, 2010 at 12:00 PM, Pjotr Kourzanov
<peter.kourzanov@xs4all.nl> wrote:
> On Tue, 2010-03-02 at 10:47 +0000, Andrew Haley wrote:
>> On 03/02/2010 10:34 AM, Pjotr Kourzanov wrote:
>>
>> >> int duff4_fails(char * dst,const char * src,const size_t n)
>> >> {
>> >>   const size_t rem=n % 4, a=rem + (!rem)*4;
>> >>   char * d=dst+=a;
>> >>   const char * s=src+=a;
>> >>   /* gcc bug? dst+=n; */
>> >>
>> >>     switch (rem) {
>> >>     case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
>> >>     /*case 0:*/    d[-4]=s[-4];
>> >>     case 3:        d[-3]=s[-3];
>> >>     case 2:        d[-2]=s[-2];
>> >>     case 1:        d[-1]=s[-1];
>> >>          }
>> >>     }
>> >>    return 0;
>> >> }
>> >> The first time around the loop the initializer (d+=n) is jumped around, so
>> >> d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
>> >> exits.
>> >
>> >   And its wrong since it shouldn't jump around the initializer.
>>
>> Sure it should.  On entry to that loop, rem == 3.
>
>  I agree, this is one of the places where referential transparency
> breaks in C. I wouldn't have expected that the compiler could or
> would put the first expression before the switch in this case:
>
> switch (rem) {
>  for(dst+=n;d<dst;d+=4,s+=4) {
> case 0: d[-4]=s[-4]; ...
> }}
>
> However, the warning is still due, since a combination of a switch with a
> for loop results in code that is completely ignored, i.e., is inaccessible.
> As I said, gcc-3.x used to issue a warning for this one...

Neither 2.95 nor 3.3.6 or 3.4.6 warn for me.

Richard.

>>
>> Andrew.
>>
>
>
>

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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02 11:26         ` Richard Guenther
@ 2010-03-02 13:07           ` Peter Kourzanov
  2010-03-04  9:16             ` Peter Kourzanov
  0 siblings, 1 reply; 11+ messages in thread
From: Peter Kourzanov @ 2010-03-02 13:07 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Andrew Haley, gcc

On Tue, 2010-03-02 at 12:26 +0100, Richard Guenther wrote: 
> On Tue, Mar 2, 2010 at 12:00 PM, Pjotr Kourzanov
> <peter.kourzanov@xs4all.nl> wrote:
> > On Tue, 2010-03-02 at 10:47 +0000, Andrew Haley wrote:
> >> On 03/02/2010 10:34 AM, Pjotr Kourzanov wrote:
> >>
> >> >> int duff4_fails(char * dst,const char * src,const size_t n)
> >> >> {
> >> >>   const size_t rem=n % 4, a=rem + (!rem)*4;
> >> >>   char * d=dst+=a;
> >> >>   const char * s=src+=a;
> >> >>   /* gcc bug? dst+=n; */
> >> >>
> >> >>     switch (rem) {
> >> >>     case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
> >> >>     /*case 0:*/    d[-4]=s[-4];
> >> >>     case 3:        d[-3]=s[-3];
> >> >>     case 2:        d[-2]=s[-2];
> >> >>     case 1:        d[-1]=s[-1];
> >> >>          }
> >> >>     }
> >> >>    return 0;
> >> >> }
> >> >> The first time around the loop the initializer (d+=n) is jumped around, so
> >> >> d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
> >> >> exits.
> >> >
> >> >   And its wrong since it shouldn't jump around the initializer.
> >>
> >> Sure it should.  On entry to that loop, rem == 3.
> >
> >  I agree, this is one of the places where referential transparency
> > breaks in C. I wouldn't have expected that the compiler could or
> > would put the first expression before the switch in this case:
> >
> > switch (rem) {
> >  for(dst+=n;d<dst;d+=4,s+=4) {
> > case 0: d[-4]=s[-4]; ...
> > }}
> >
> > However, the warning is still due, since a combination of a switch with a
> > for loop results in code that is completely ignored, i.e., is inaccessible.
> > As I said, gcc-3.x used to issue a warning for this one...
> 
> Neither 2.95 nor 3.3.6 or 3.4.6 warn for me.

That's weird. I am having:

gcc-3.3 (GCC) 3.3.6 (Ubuntu 1:3.3.6-15ubuntu6)
Configured with: ../src/configure -v --enable-languages=c,c++
--prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info
--with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared
--enable-__cxa_atexit --with-system-zlib --enable-nls
--without-included-gettext --enable-clocale=gnu --enable-debug
i486-linux-gnu
Thread model: posix
gcc-3.4 (GCC) 3.4.6 (Ubuntu 3.4.6-8ubuntu2)
Configured with: ../src/configure -v --enable-languages=c,f77
--prefix=/usr --libexecdir=/usr/lib
--with-gxx-include-dir=/usr/include/c++/3.4 --enable-shared
--with-system-zlib --enable-nls --without-included-gettext
--program-suffix=-3.4 --enable-__cxa_atexit --with-tune=pentium4
i486-linux-gnu
Thread model: posix

Are you sure you test the following variant?

switch (rem) { 
for(dst+=n;d<dst;d+=4,s+=4) {
 case 0: d[-4]=s[-4]; ...
}}

> 
> Richard.
> 
> >>
> >> Andrew.
> >>
> >
> >
> >
> 


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

* Re: gcc miscompiling duff's device (probaby two different bugs)
  2010-03-02 13:07           ` Peter Kourzanov
@ 2010-03-04  9:16             ` Peter Kourzanov
  0 siblings, 0 replies; 11+ messages in thread
From: Peter Kourzanov @ 2010-03-04  9:16 UTC (permalink / raw)
  To: gcc

Dear all,

  Although I probably shouldn't have been so harsh calling this
"mis-compiling", do you see any chance of back-porting this warning back
into the mainline? 

P.S. The rationale of this exercise is of course that the "switch",
being a goto in disguise needs careful attention, just like the goto.
So combining it a-la Tom Duff with another construct blessed by
Dijkstra, the for loop, can sometimes lead to unexpected results.

Pjotr

On Tue, 2010-03-02 at 14:07 +0100, Peter Kourzanov wrote: 
> On Tue, 2010-03-02 at 12:26 +0100, Richard Guenther wrote: 
> > On Tue, Mar 2, 2010 at 12:00 PM, Pjotr Kourzanov
> > <peter.kourzanov@xs4all.nl> wrote:
> > > On Tue, 2010-03-02 at 10:47 +0000, Andrew Haley wrote:
> > >> On 03/02/2010 10:34 AM, Pjotr Kourzanov wrote:
> > >>
> > >> >> int duff4_fails(char * dst,const char * src,const size_t n)
> > >> >> {
> > >> >>   const size_t rem=n % 4, a=rem + (!rem)*4;
> > >> >>   char * d=dst+=a;
> > >> >>   const char * s=src+=a;
> > >> >>   /* gcc bug? dst+=n; */
> > >> >>
> > >> >>     switch (rem) {
> > >> >>     case 0:  for(dst+=n;d<dst;d+=4,s+=4) {
> > >> >>     /*case 0:*/    d[-4]=s[-4];
> > >> >>     case 3:        d[-3]=s[-3];
> > >> >>     case 2:        d[-2]=s[-2];
> > >> >>     case 1:        d[-1]=s[-1];
> > >> >>          }
> > >> >>     }
> > >> >>    return 0;
> > >> >> }
> > >> >> The first time around the loop the initializer (d+=n) is jumped around, so
> > >> >> d == dst.  At the end of the loop, d+=4, so d > dst.  Therefore the loop
> > >> >> exits.
> > >> >
> > >> >   And its wrong since it shouldn't jump around the initializer.
> > >>
> > >> Sure it should.  On entry to that loop, rem == 3.
> > >
> > >  I agree, this is one of the places where referential transparency
> > > breaks in C. I wouldn't have expected that the compiler could or
> > > would put the first expression before the switch in this case:
> > >
> > > switch (rem) {
> > >  for(dst+=n;d<dst;d+=4,s+=4) {
> > > case 0: d[-4]=s[-4]; ...
> > > }}
> > >
> > > However, the warning is still due, since a combination of a switch with a
> > > for loop results in code that is completely ignored, i.e., is inaccessible.
> > > As I said, gcc-3.x used to issue a warning for this one...
> > 
> > Neither 2.95 nor 3.3.6 or 3.4.6 warn for me.
> 
> That's weird. I am having:
> 
> gcc-3.3 (GCC) 3.3.6 (Ubuntu 1:3.3.6-15ubuntu6)
> Configured with: ../src/configure -v --enable-languages=c,c++
> --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info
> --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared
> --enable-__cxa_atexit --with-system-zlib --enable-nls
> --without-included-gettext --enable-clocale=gnu --enable-debug
> i486-linux-gnu
> Thread model: posix
> gcc-3.4 (GCC) 3.4.6 (Ubuntu 3.4.6-8ubuntu2)
> Configured with: ../src/configure -v --enable-languages=c,f77
> --prefix=/usr --libexecdir=/usr/lib
> --with-gxx-include-dir=/usr/include/c++/3.4 --enable-shared
> --with-system-zlib --enable-nls --without-included-gettext
> --program-suffix=-3.4 --enable-__cxa_atexit --with-tune=pentium4
> i486-linux-gnu
> Thread model: posix
> 
> Are you sure you test the following variant?
> 
> switch (rem) { 
> for(dst+=n;d<dst;d+=4,s+=4) {
>  case 0: d[-4]=s[-4]; ...
> }}
> 
> > 
> > Richard.
> > 
> > >>
> > >> Andrew.
> > >>
> > >
> > >
> > >
> > 
> 
> 


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

end of thread, other threads:[~2010-03-04  9:16 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-02  9:38 gcc miscompiling duff's device (probaby two different bugs) Peter Kourzanov
2010-03-02 10:24 ` Andrew Haley
2010-03-02 10:34   ` Pjotr Kourzanov
2010-03-02 10:47     ` Andrew Haley
2010-03-02 11:00       ` Pjotr Kourzanov
2010-03-02 11:26         ` Richard Guenther
2010-03-02 13:07           ` Peter Kourzanov
2010-03-04  9:16             ` Peter Kourzanov
2010-03-02 10:27 ` Richard Guenther
2010-03-02 10:39   ` Pjotr Kourzanov
2010-03-02 10:58 ` Andreas Schwab

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).