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.

Reply via email to