tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] Bugs found in TCC


From: Yann Bourrigault
Subject: [Tinycc-devel] Bugs found in TCC
Date: Fri, 22 Jan 2010 15:49:06 +0000

Hello,

 

My company is looking for a tiny compiler to embed in its product, in order to build some generated source code. As TCC seems to fit our needs, I have launched our compiler validation test base on it. I actually found several bugs, which are not blocking for our purposes, but may interest you. Here’s a list of the bugs followed by reproduction steps, in the form of source code to compile. Most of them were first tested against gcc and worked well with it.

 

 

->Tcc refuses to compile bitfield assignment when a side effect occurs on a double.

Reproduction steps:
struct {
int field : 8;
int field2 : 8;
unsigned int ufield : 8;
unsigned int ufield2 : 8;
} bit;

double d1;

void main() {
bit.field = ++d1;
}

->In some cases, Tcc refuses to compile codes defining types with the same names but in different scopes.

Reproduction steps:

int f(struct xyz { int xyz; } *xyz)

{

                return xyz->xyz;

}

 

void main() {

  struct xyz { int xyz; } buf;

}

 

->In some cases, Tcc refuses to compile codes defining variables with the same names but in different scopes.

 

Reproduction steps:

#include <assert.h>

 

float float_foo = 2.0;

 

void test() {

  static float foo = 5.0;

 

  {

    extern int foo;

    foo = 15;

  }

  float_foo = foo;

}

 

int foo = 1;

 

void main() {

  assert(foo == 1);

  assert(float_foo == 2.0);

  test();

  assert(foo == 15);

  assert(float_foo == 5.0);

}

->Tcc refuses to compile codes with a static initializer containing boolean operation on doubles.

Reproduction steps:
static int t5 = 1 && 2.1;

->Tcc returns a strange compilation error "missing ;" when the code contains extern having initializer.

Reproduction steps:
extern int i4 = 10;

->Tcc doesn't support correctly typedefs to incomplete types.

Reproduction steps:
typedef int table[];

table 1 };
table two = { 1, 2 }; // error: index too large

->Tcc doesn't fetch float argument in old style definition as double, causing wrong values to be passed.

Reproduction steps:

int bug(f, d)
float f;
int d;
{
return d == 42;
}

void main()
{
assert(bug(3.14, 42) == 1);
}

->Some complex sizeof are not computed correctly by Tcc, returning wrong results.

Reproduction steps:
int x = 0;
char a[100];
char b[50];

void main()

{
assert(sizeof(x == 0 ? a : b) == sizeof(char *));

}

->Problem with implicit casts on bitfields. Assigning a bitfield to an unsigned short or unsigned char without an explicit cast leads to a wrong value.

Reproduction steps:

#include <assert.h>

struct bit {

  int dummy;

  int f0 :  7;

  int f1 : 13;

  int f5 : 32  - 2;

  int f3 : 32  - 1;

  int f4 : 32 ;

};

int main() {

  struct bit bit;

  unsigned short ush0, ush1, ush3, ush4;

  unsigned char uch0, uch1, uch3, uch4;

  unsigned int mask = 0xffffU;

 

  bit.f0 = 63;

  bit.f1 = 4095;

  bit.f3 = 1023441823;

  bit.f4 = 2113483647;

  /* Those assignments give wrong results */

  ush0 = bit.f0;

  ush1 = bit.f1;

  ush3 = bit.f3;

  ush4 = bit.f4;

 

  assert(ush0 == 63);

  assert(ush1 == 4095);

  assert(ush3 == (bit.f3 & mask));

  assert(ush4 == (bit.f4 & mask));

  mask = 0xffU;

   /* Those assignments give wrong results */

  uch0 = bit.f0;

  uch1 = bit.f1;

  uch3 = bit.f3;

  uch4 = bit.f4;

 

  assert(uch0 == 63);

  assert(uch1 == (bit.f1 & mask));

  assert(uch3 == (bit.f3 & mask));

  assert(uch4 == (bit.f4 & mask));

 

  return 0;

}

->Problem with promotion on bitfields. Some integral promotion are wrong with bitfields.

Reproduction steps:

#include <assert.h>

int main() {

  struct {

    unsigned int ufield  : 7;

    int  field  : 7;

    int  field2 : 7;

  } bit;

  int i1;

  short sh1;

  char ch1;

  bit.ufield = 10;

  i1         =  -11;

  assert((bit.ufield + i1) < 0);

  sh1        =  -11;

  assert((bit.ufield + sh1) < 0);

  bit.field  =  -11;

  assert((bit.ufield + bit.field) < 0);

  ch1 = -11;

  assert((bit.ufield + ch1) < 0);

  return 0;

}


->When declaring local extern variables, the compiler should look for global variables before looking for local ones.

Reproduction steps:
int v = 3;

void main()
{
int v = 4;
{
extern int v;
assert(v == 3);
}
}

->When returning an element with an implicit cast to float, the value is wrong.

Reproduction steps:
float f_dbl(double dbl)
{
   return dbl;
}

float f_ui(unsigned int ui)
{
   return ui;
}

void main() {
   float  f;
   double d;
   unsigned int ui;

   d = -5.9;
   f = d;;

   assert(f == f_dbl(d));

   ui = 0;
   ui = ~ui;
   f  = ui;

   assert(f == f_ui(ui));
}

->The padding is not generated correctly when initializing unions statically.

Reproduction steps:
union {
char c;
double d;
} u[2] = { 'a', 'b' };

void main()
{
   u[0].d = 3.4;
   assert(u[1].c == 'b');
}

->Tcc refuses to compile code when an overflow occurs on static initialization. A warning should only be issued.

Reproduction steps:
int x = 123456789012345678901234567;

 

 

-> A memcpy or memset is sometimes introduced for functions returning a struct and causes compilation errors is string.h is included afterward.

 

Reproduction steps:

#include <assert.h>

 

struct s {

  int a;

};

 

struct s test() {

  struct s ms;

 

  ms.a = 1;

 

  return ms;

}

 

int main() {

  struct s ls;

 

  ls = test();

 

  assert(ls.a == 1);

 

  return 0;

}

 

#include <string.h>

 

 

-> Incomplete types lead to an error if not defined, whereas they should be assumed as having only one element.

 

Reproduction steps:

char test[];

 

int main() {

  test[0] = 0;

}

 

 

-> Computations on very big values stored in long doubles gives wrong results.

 

#include <float.h>

#include <assert.h>

 

#define X  5.9486574767861588254287966331400356538172e4931L

 

int main() {

  long double test;

  int exponent = 0;

 

  test = X;

 

  test *= 2.0L;

 

  assert(test > LDBL_MAX);

 

  return 0;

}

 

 

Hope this helps!

 

Regards,

 

Yann Bourrigault.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]