Issue Details (XML | Word | Printable)

Key: PCC-462
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Anders Magnusson
Reporter: Volkmar Klatt
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
pcc

test for conversion ranks of bitfield types

Created: 03/Aug/14 01:10 AM   Updated: 06/Aug/14 05:24 PM
Component/s: None
Affects Version/s: None
Fix Version/s: None

File Attachments: 1. Text File tr_20140731_49.c (5 kB)

Environment:
pcc 1.1.0.DEVEL 20140729 for i686-pc-linux-gnu


 Description  « Hide
/* tr_20140731_49.c - test file for pcc, Volkmar Klatt
   test for conversion ranks of bitfield types

   pcc 1.1.0.DEVEL 20140729 for i686-pc-linux-gnu

   usage:
   gcc tr_20140731_49.c -o z or clang/cparser,...
   pcc tr_20140731_49.c -o zz
   ./z # all '>'
   ./zz */

#include <stdio.h>

struct SCHAR {
   unsigned char f0 : 7;
   signed char f1 : 7;
};

struct SSHORT {
   unsigned short f0 : 7;
   signed short f1 : 7;
};

struct SINT {
   unsigned f0 : 7;
   signed f1 : 7;
};

struct SLONG {
   unsigned long f0 : 7;
   signed long f1 : 7;
};

struct SLONGLONG {
   unsigned long long f0 : 7;
   signed long long f1 : 7;
};

struct S_CHAR_SHORT {
   unsigned char f0 : 7;
   signed short f1 : 7;
};

struct S_SHORT_CHAR {
   unsigned short f0 : 7;
   signed char f1 : 7;
};

struct S_CHAR_INT {
   unsigned char f0 : 7;
   signed int f1 : 7;
};

struct S_INT_CHAR {
   unsigned int f0 : 7;
   signed char f1 : 7;
};

struct S_CHAR_LONG {
   unsigned char f0 : 7;
   signed long f1 : 7;
};

struct S_LONG_CHAR {
   unsigned long f0 : 7;
   signed char f1 : 7;
};

struct S_CHAR_LONGLONG {
   unsigned char f0 : 7;
   signed long long f1 : 7;
};

struct S_LONGLONG_CHAR {
   unsigned long long f0 : 7;
   signed char f1 : 7;
};

struct S_SHORT_INT {
   unsigned short f0 : 7;
   signed int f1 : 7;
};

struct S_INT_SHORT {
   unsigned int f0 : 7;
   signed short f1 : 7;
};

struct S_SHORT_LONG {
   unsigned short f0 : 7;
   signed long f1 : 7;
};

struct S_LONG_SHORT {
   unsigned long f0 : 7;
   signed short f1 : 7;
};

struct S_SHORT_LONGLONG {
   unsigned short f0 : 7;
   signed long long f1 : 7;
};

struct S_LONGLONG_SHORT {
   unsigned long long f0 : 7;
   signed short f1 : 7;
};

struct S_INT_LONG {
   unsigned int f0 : 7;
   signed long f1 : 7;
};

struct S_LONG_INT {
   unsigned long f0 : 7;
   signed int f1 : 7;
};

struct S_INT_LONGLONG {
   unsigned int f0 : 7;
   signed long long f1 : 7;
};

struct S_LONGLONG_INT {
   unsigned long long f0 : 7;
   signed int f1 : 7;
};



int main (void)
{
   struct SCHAR sc = {2,-2};
   struct SSHORT ss = {2,-2};
   struct SINT si = {2,-2};
   struct SLONG sl = {2,-2};
   struct SLONGLONG sll = {2,-2};

   struct S_CHAR_SHORT scs = {2,-2};
   struct S_SHORT_CHAR ssc = {2,-2};
   struct S_CHAR_INT sci = {2,-2};
   struct S_INT_CHAR sic = {2,-2};
   struct S_CHAR_LONG scl = {2,-2};
   struct S_LONG_CHAR slc = {2,-2};
   struct S_CHAR_LONGLONG scll = {2,-2};
   struct S_LONGLONG_CHAR sllc = {2,-2};

   struct S_SHORT_INT ssi = {2,-2};
   struct S_INT_SHORT sis = {2,-2};
   struct S_SHORT_LONG ssl = {2,-2};
   struct S_LONG_SHORT sls = {2,-2};
   struct S_SHORT_LONGLONG ssll = {2,-2};
   struct S_LONGLONG_SHORT slls = {2,-2};

   struct S_INT_LONG sil = {2,-2};
   struct S_LONG_INT sli = {2,-2};
   struct S_INT_LONGLONG sill = {2,-2};
   struct S_LONGLONG_INT slli = {2,-2};

   if (sc.f0 > sc.f1)
      printf("sc >\n"); else printf("sc <\n"); // OK

   if (ss.f0 > ss.f1)
      printf("ss >\n"); else printf("ss <\n"); // OK

   if (si.f0 > si.f1)
      printf("si >\n"); else printf("si <\n");

   if (sl.f0 > sl.f1)
      printf("sl >\n"); else printf("sl <\n");

   if (sll.f0 > sll.f1)
      printf("sll >\n"); else printf("sll <\n");

/* combinations: */
   if (scs.f0 > scs.f1)
      printf("scs >\n"); else printf("scs <\n"); // OK

   if (ssc.f0 > ssc.f1)
      printf("ssc >\n"); else printf("ssc <\n"); // OK

   if (sci.f0 > sci.f1)
      printf("sci >\n"); else printf("sci <\n"); // OK

   if (sic.f0 > sic.f1)
      printf("sic >\n"); else printf("sic <\n");

   if (scl.f0 > scl.f1)
      printf("scl >\n"); else printf("scl <\n"); // OK

   if (slc.f0 > slc.f1)
      printf("slc >\n"); else printf("slc <\n");

   if (scll.f0 > scll.f1)
      printf("scll >\n"); else printf("scll <\n"); // OK

   if (sllc.f0 > sllc.f1)
      printf("sllc >\n"); else printf("sllc <\n");

   if (ssi.f0 > ssi.f1)
      printf("ssi >\n"); else printf("ssi <\n"); // OK

   if (sis.f0 > sis.f1)
      printf("sis >\n"); else printf("sis <\n");

   if (ssl.f0 > ssl.f1)
      printf("ssl >\n"); else printf("ssl <\n"); // OK

   if (sls.f0 > sls.f1)
      printf("sls >\n"); else printf("sls <\n");

   if (ssll.f0 > ssll.f1)
      printf("ssll >\n"); else printf("ssll <\n"); // OK

   if (slls.f0 > slls.f1)
      printf("slls >\n"); else printf("slls <\n");

   if (sil.f0 > sil.f1)
      printf("sil >\n"); else printf("sil <\n");

   if (sli.f0 > sli.f1)
      printf("sli >\n"); else printf("sli <\n");

   if (sill.f0 > sill.f1)
      printf("sill >\n"); else printf("sill <\n"); // OK

   if (slli.f0 > slli.f1)
      printf("slli >\n"); else printf("slli <\n");



   return 0;
}




 All   Comments   Change History      Sort Order: Ascending order - Click to sort in descending order
Volkmar Klatt added a comment - 05/Aug/14 02:43 PM
maybe this helps:

/* tr_20140805_50.c - test file for pcc - Volkmar Klatt
   comparisons between an unsigned bitfield and
   a signed bitfield go wrong.

   pcc 1.1.0.DEVEL 20140804 for i686-pc-linux-gnu
   
   usage:
   gcc tr_20140805_50.c -o z # or other compiler
   pcc tr_20140805_50.c -o zz
   ./z --> <
   ./zz --> > */

#include <stdio.h>

struct S {
   signed f1 : 26;
   unsigned f2 : 26;
};

struct S s = {-1, 0};


int main ()
{
    if (s.f1 > s.f2)
       printf(">\n");
    else
       printf("<\n");

    return 0;
}



Volkmar Klatt added a comment - 05/Aug/14 02:44 PM
addendum 2:

/* tr_20140805_52.c - test file for pcc - Volkmar Klatt
   comparisons between an unsigned bitfield and
   a negative char (== signed char) go wrong.

   pcc 1.1.0.DEVEL 20140804 for i686-pc-linux-gnu
   
   usage:
   gcc tr_20140805_51.c -o z # or other compiler
   pcc tr_20140805_51.c -o zz
   ./z --> >
   ./zz --> < */

#include <stdio.h>

struct S {
   unsigned f : 5;
};

struct S s = {1};
/* == signed char in pcc */ char c = 128; /* overflow --> -128 */

int main (void)
{
    if (s.f > c)
       printf(">\n");
    else
       printf("<\n");

    return 0;
}



Volkmar Klatt added a comment - 05/Aug/14 02:45 PM
addendum 3:

/* tr_20140805_53.c - test file for pcc - Volkmar Klatt
   issue: the range of signed bitfields is wrong,
   hence their overflow/underflow is incorrect, too.
   (they are handled like unsigned bitfields)

   pcc 1.1.0.DEVEL 20140804 for i686-pc-linux-gnu

   usage:
   gcc tr_20140805_53.c -o z # or other compiler
   pcc tr_20140805_53.c -o zz
   ./z --> -2 -2
   ./zz --> 2 -2 */


#include <stdio.h>

struct S {
   signed f : 2;
};

struct S s = {1};

int main (void)
{
   int i;
    
   i = (s.f = -2); /* -2 should not underflow a signed bitfield of width 2 [ -2,-1,-0,1] */
   printf("%i\n", i); /* pcc: 2 */
   printf("%i\n", s.f);

/* furthermore:
     n pcc gcc
     ...
     4 0 0
     3 3 -1
     2 2 -2
     1 1 1
     0 0 0
    -1 3 -1
    -2 2 -2
    -3 1 1
    -4 0 0
    -5 3 -1
    -6 2 -2
    -7 1 1
    -8 0 0
    -9 3 -1
   -10 2 -2
    ...
  cf. Harbison Steele 5 ed. (Sec. 5.6 Structure Types) p. 155:
    "A bit field of n bits can represent
     unsigned integers in the range 0 through +2**n -1
     and signed integers in the range -2**(n-1) through +2**(n-1) -1,
     assuming a twos-complement representation of signed integers." */

   return 0;
}



Anders Magnusson added a comment - 06/Aug/14 11:28 AM
Bit-fields other than int, unsigned and _Bool are implementation-defined.
Nevertheless, to avoid surprises, pcc should handle these as gcc. I'll add appropriate promotions.

Anders Magnusson added a comment - 06/Aug/14 05:24 PM
I've now added integer promotions to all bitfield operations in the same way as gcc does, so now it work. Thanks!