|
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: 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); } void main() { } 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; } 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; }
-> 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. |
[Prev in Thread] | Current Thread | [Next in Thread] |