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