This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gcc miscompiling duff's device (probaby two different bugs)


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
#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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]