mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 23:54:16 +08:00
Some checks are pending
build and test / test-x86_64-linux (push) Waiting to run
build and test / test-x86_64-osx (push) Waiting to run
build and test / test-aarch64-osx (push) Waiting to run
build and test / test-x86_64-win32 (push) Waiting to run
build and test / test-i386-win32 (push) Waiting to run
build and test / test-armv7-linux (push) Waiting to run
build and test / test-aarch64-linux (push) Waiting to run
build and test / test-riscv64-linux (push) Waiting to run
While adding some testcases for attribute cleanup I found a bug in the riscv code. It modifies the sv->c.i in load_symofs. If a structure contains more then one element only the first is stored correctly. This only happens on a large stack frame. Fixed by saving/restoring sv->c.i.
360 lines
7.3 KiB
C
360 lines
7.3 KiB
C
extern int printf(const char*, ...);
|
|
static int glob_i = 0;
|
|
|
|
typedef struct { int a; int b; int c; int d; int e; int f; int g; int h; } tstl;
|
|
typedef struct { int a; int b; int c; int d; } tsti;
|
|
typedef struct { double a; double b; } tstd;
|
|
typedef struct { long double a; } tstld;
|
|
typedef struct { int a; double b; } tstm;
|
|
typedef struct { float a; float b; float c; float d; } tstf;
|
|
|
|
void incr_glob_i(int *i)
|
|
{
|
|
glob_i += *i;
|
|
*i = -1;
|
|
}
|
|
|
|
#define INCR_GI { \
|
|
int i __attribute__ ((__cleanup__(incr_glob_i))) = 1; \
|
|
}
|
|
|
|
#define INCR_GI0 INCR_GI INCR_GI INCR_GI INCR_GI
|
|
#define INCR_GI1 INCR_GI0 INCR_GI0 INCR_GI0 INCR_GI0
|
|
#define INCR_GI2 INCR_GI1 INCR_GI1 INCR_GI1 INCR_GI1
|
|
#define INCR_GI3 INCR_GI2 INCR_GI2 INCR_GI2 INCR_GI2
|
|
#define INCR_GI4 INCR_GI3 INCR_GI3 INCR_GI3 INCR_GI3
|
|
#define INCR_GI5 INCR_GI4 INCR_GI4 INCR_GI4 INCR_GI4
|
|
#define INCR_GI6 INCR_GI5 INCR_GI5 INCR_GI5 INCR_GI5
|
|
#define INCR_GI7 INCR_GI6 INCR_GI6 INCR_GI6 INCR_GI6
|
|
|
|
|
|
void check2(char **hum);
|
|
|
|
void check(int *j)
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) stop_that = "wololo";
|
|
int chk = 0;
|
|
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) stop_that = "plop";
|
|
|
|
{
|
|
non_plopage:
|
|
printf("---- %d\n", chk);
|
|
}
|
|
if (!chk) {
|
|
chk = 1;
|
|
goto non_plopage;
|
|
}
|
|
}
|
|
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) stop_that = "tata !";
|
|
|
|
goto out;
|
|
stop_that = "titi";
|
|
}
|
|
again:
|
|
chk = 2;
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) cascade1 = "1";
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) cascade2 = "2";
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) cascade3 = "3";
|
|
|
|
goto out;
|
|
cascade3 = "nope";
|
|
}
|
|
}
|
|
}
|
|
out:
|
|
if (chk != 2)
|
|
goto again;
|
|
{
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) out = "last goto out";
|
|
++chk;
|
|
if (chk != 3)
|
|
goto out;
|
|
}
|
|
}
|
|
*j = -1;
|
|
return;
|
|
}
|
|
|
|
void check_oh_i(char *oh_i)
|
|
{
|
|
printf("c: %c\n", *oh_i);
|
|
*oh_i = '0';
|
|
}
|
|
|
|
void goto_hell(double *f)
|
|
{
|
|
printf("oo: %f\n", *f);
|
|
*f = -1.0;
|
|
}
|
|
|
|
char *test()
|
|
{
|
|
char *__attribute__ ((cleanup(check2))) str = "I don't think this should be print(but gcc got it wrong too)";
|
|
|
|
return str;
|
|
}
|
|
|
|
void test_ret_subcall(char *that)
|
|
{
|
|
printf("should be print before\n");
|
|
}
|
|
|
|
void test_ret()
|
|
{
|
|
char *__attribute__ ((cleanup(check2))) that = "that";
|
|
return test_ret_subcall(that);
|
|
}
|
|
|
|
void test_ret2()
|
|
{
|
|
char *__attribute__ ((cleanup(check2))) that = "-that";
|
|
{
|
|
char *__attribute__ ((cleanup(check2))) that = "this should appear only once";
|
|
}
|
|
{
|
|
char *__attribute__ ((cleanup(check2))) that = "-that2";
|
|
return;
|
|
}
|
|
}
|
|
|
|
void test2(void) {
|
|
int chk = 0;
|
|
again:
|
|
if (!chk) {
|
|
char * __attribute__ ((cleanup(check2))) stop_that = "test2";
|
|
chk++;
|
|
goto again;
|
|
}
|
|
}
|
|
|
|
int test3(void) {
|
|
char * __attribute__ ((cleanup(check2))) stop_that = "three";
|
|
int chk = 0;
|
|
|
|
if (chk) {
|
|
{
|
|
outside:
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) stop_that = "two";
|
|
printf("---- %d\n", chk);
|
|
}
|
|
}
|
|
}
|
|
if (!chk)
|
|
{
|
|
char * __attribute__ ((cleanup(check2))) stop_that = "one";
|
|
|
|
if (!chk) {
|
|
chk = 1;
|
|
goto outside;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void cl(int *ip)
|
|
{
|
|
printf("%d\n", *ip);
|
|
*ip = -1;
|
|
}
|
|
|
|
void loop_cleanups(void)
|
|
{
|
|
__attribute__((cleanup(cl))) int l = 1000;
|
|
|
|
printf("-- loop 0 --\n");
|
|
for ( __attribute__((cleanup(cl))) int i = 0; i < 10; ++i) {
|
|
__attribute__((cleanup(cl))) int j = 100;
|
|
}
|
|
|
|
printf("-- loop 1 --\n");
|
|
for (__attribute__((cleanup(cl))) int i = 0; i < 10; ++i) {
|
|
__attribute__((cleanup(cl))) int j = 200;
|
|
continue;
|
|
}
|
|
|
|
printf("-- loop 2 --\n");
|
|
for (__attribute__((cleanup(cl))) int i = 0; i < 10; ++i) {
|
|
__attribute__((cleanup(cl))) int j = 300;
|
|
break;
|
|
}
|
|
|
|
printf("-- loop 3 --\n");
|
|
for (int i = 0; i < 2; ++i) {
|
|
__attribute__((cleanup(cl))) int j = 400;
|
|
switch (i) {
|
|
case 0:
|
|
continue;
|
|
default:
|
|
{
|
|
__attribute__((cleanup(cl))) int jj = 500;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
printf("after break\n");
|
|
}
|
|
|
|
void my_cleanup1(int *p) {
|
|
printf("%d\n", *p);
|
|
*p = 0x90;
|
|
}
|
|
|
|
int test_cleanup1(void) {
|
|
int __attribute__((cleanup(my_cleanup1))) n = 42;
|
|
return n;
|
|
}
|
|
|
|
void my_cleanup2(tstl *p) {
|
|
printf("%d %d %d %d %d %d %d %d\n", p->a, p->b, p->c, p->d,
|
|
p->e, p->f, p->g, p->h);
|
|
p->a = 0x90; p->b = 0x91; p->c = 0x92; p->d = 0x93;
|
|
p->e = 0x94; p->f = 0x95; p->g = 0x96; p->h = 0x97;
|
|
}
|
|
|
|
tstl test_cleanup2(void) {
|
|
tstl __attribute__((cleanup(my_cleanup2))) n;
|
|
n.a = 42; n.b = 43; n.c = 44; n.d = 45;
|
|
n.e = 46; n.f = 47; n.g = 48; n.h = 49;
|
|
return n;
|
|
}
|
|
|
|
void my_cleanup3(tsti *p) {
|
|
printf("%d %d %d %d\n", p->a, p->b, p->c, p->d);
|
|
p->a = 0x90; p->b = 0x91; p->c = 0x92; p->d = 0x93;
|
|
}
|
|
|
|
tsti test_cleanup3(void) {
|
|
tsti __attribute__((cleanup(my_cleanup3))) n;
|
|
n.a = 42; n.b = 43; n.c = 44; n.d = 45;
|
|
return n;
|
|
}
|
|
|
|
void my_cleanup4(tstd *p) {
|
|
printf("%g %g\n", p->a, p->b);
|
|
p->a = 90.0; p->b = 91.0;
|
|
}
|
|
|
|
tstd test_cleanup4(void) {
|
|
tstd __attribute__((cleanup(my_cleanup4))) n;
|
|
n.a = 42.0; n.b = 43.0;
|
|
return n;
|
|
}
|
|
|
|
void my_cleanup5(tstld *p) {
|
|
printf("%Lf\n", p->a);
|
|
p->a = 90.0;
|
|
}
|
|
|
|
tstld test_cleanup5(void) {
|
|
tstld __attribute__((cleanup(my_cleanup5))) n;
|
|
n.a = 42.0;
|
|
return n;
|
|
}
|
|
|
|
void my_cleanup6(tstm *p) {
|
|
printf("%d %g\n", p->a, p->b);
|
|
p->a = 90;
|
|
p->b = 91.0;
|
|
}
|
|
|
|
tstm test_cleanup6(void) {
|
|
tstm __attribute__((cleanup(my_cleanup6))) n;
|
|
n.a = 42;
|
|
n.b = 43.0;
|
|
return n;
|
|
}
|
|
|
|
void my_cleanup7(tstf *p) {
|
|
printf("%f %f %f %f\n", p->a, p->b, p->c, p->d);
|
|
p->a = 0x90; p->b = 0x91; p->c = 0x92; p->d = 0x93;
|
|
}
|
|
|
|
tstf test_cleanup7(void) {
|
|
tstf __attribute__((cleanup(my_cleanup7))) n;
|
|
n.a = 42; n.b = 43; n.c = 44; n.d = 45;
|
|
return n;
|
|
}
|
|
|
|
void my_cleanup8(int **p) {
|
|
**p = 0x90;
|
|
}
|
|
|
|
int test_cleanup8(void) {
|
|
int n = 42;
|
|
int __attribute__((cleanup(my_cleanup8))) *p = &n;
|
|
return n;
|
|
}
|
|
|
|
static void my_cleanupe(int *p) {
|
|
*p = 0x90;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
int i __attribute__ ((__cleanup__(check))) = 0, not_i;
|
|
int chk = 0;
|
|
(void)not_i;
|
|
tstl tl;
|
|
tsti ti;
|
|
tstd td;
|
|
tstld tld;
|
|
tstm tm;
|
|
tstf tf;
|
|
|
|
{
|
|
__attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'o', o = 'a';
|
|
}
|
|
|
|
INCR_GI7;
|
|
printf("glob_i: %d\n", glob_i);
|
|
naaaaaaaa:
|
|
if (!chk) {
|
|
__attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'f';
|
|
double __attribute__ ((__cleanup__(goto_hell))) f = 2.6;
|
|
|
|
chk = 1;
|
|
goto naaaaaaaa;
|
|
}
|
|
i = 105;
|
|
printf("because what if free was call inside cleanup function %s\n", test());
|
|
test_ret();
|
|
test_ret2();
|
|
test2();
|
|
test3();
|
|
loop_cleanups();
|
|
printf("%d\n", test_cleanup1());
|
|
tl = test_cleanup2();
|
|
printf("%d %d %d %d %d %d %d %d\n", tl.a, tl.b, tl.c, tl.d,
|
|
tl.e, tl.f, tl.g, tl.h);
|
|
ti = test_cleanup3();
|
|
printf("%d %d %d %d\n", ti.a, ti.b, ti.c, ti.d);
|
|
td = test_cleanup4();
|
|
printf("%g %g\n", td.a, td.b);
|
|
tld = test_cleanup5();
|
|
printf("%Lf\n", tld.a);
|
|
tm = test_cleanup6();
|
|
printf("%d %g\n", tm.a, tm.b);
|
|
tf = test_cleanup7();
|
|
printf("%f %f %f %f\n", tf.a, tf.b, tf.c, tf.d);
|
|
printf("%d\n", test_cleanup8());
|
|
printf("%d\n", ({
|
|
int __attribute__ ((cleanup(my_cleanupe))) n = 42;
|
|
n; }));
|
|
return i;
|
|
}
|
|
|
|
void check2(char **hum)
|
|
{
|
|
printf("str: %s\n", *hum);
|
|
*hum = "fail";
|
|
}
|