[qfcc] Add breaking assignment chain test

This bug drove me nuts for several hours until I figured out what was
going on.
The assignment sub-tree is being generated, then lost. It works for
simple assignments because a = b = c -> (= a (= b c)), but for complex
assignments (those that require move or memset), a = b = c -> (b = c) (a
= c) but nothing points to (b = c). The cause is using binary
expressions to store assignments.
This commit is contained in:
Bill Currie 2020-03-12 19:47:09 +09:00
parent 4c2a6c9eb2
commit f454842361
2 changed files with 99 additions and 0 deletions

View file

@ -31,6 +31,7 @@ fail_bins=
test_progs_dat=\
address-cast.dat \
alignment.dat \
assignchain.dat \
anonstruct.dat \
chewed-alias.dat \
chewed-return.dat \
@ -132,6 +133,15 @@ anonstruct.run: Makefile build-run
include ./$(DEPDIR)/anonstruct.Qo # am--include-marker
r_depfiles_remade += ./$(DEPDIR)/anonstruct.Qo
assignchain_dat_SOURCES=assignchain.r
assignchain_obj=$(assignchain_dat_SOURCES:.r=.qfo)
assignchain.dat$(EXEEXT): $(assignchain_obj) $(QFCC_DEP)
$(QFCC) $(QCFLAGS) -o $@ $(assignchain_obj)
assignchain.run: Makefile build-run
@$(srcdir)/build-run $@
include ./$(DEPDIR)/assignchain.Qo # am--include-marker
r_depfiles_remade += ./$(DEPDIR)/assignchain.Qo
chewed_alias_dat_SOURCES=chewed-alias.r
chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo)
chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP)

View file

@ -0,0 +1,89 @@
#include "test-harness.h"
typedef struct foo {
int x;
float y;
} foo;
int x, y;
int z = 42;
foo bar, baz;
foo foo_init = { 5, 6.25 };
int test_simple_global (void)
{
int ret = 0;
x = y = z;
if (x != z || y != z) {
printf ("test_simple_global: x=%d y=%d z=%d\n", x, y, z);
ret |= 1;
}
return ret;
}
int test_struct_global (void)
{
int ret = 0;
bar = baz = foo_init;
if (bar.x != foo_init.x || bar.y != foo_init.y) {
printf ("test_struct: bar={%d %g} foo_init={%d %g}\n",
bar.x, bar.y, foo_init.x, foo_init.y);
ret |= 1;
}
if (baz.x != foo_init.x || baz.y != foo_init.y) {
printf ("test_struct: baz={%d %g} foo_init={%d %g}\n",
baz.x, baz.y, foo_init.x, foo_init.y);
ret |= 1;
}
bar = baz = nil;
if (bar.x || baz.x || bar.y || baz.y) {
printf ("test_struct: bar={%d %g} baz={%d %g}\n",
bar.x, bar.y, baz.x, baz.y);
ret |= 1;
}
return ret;
}
int test_simple_pointer (int *x, int *y)
{
int ret = 0;
*x = *y = z;
if (*x != z || *y != z) {
printf ("test_simple_global: *x=%d *y=%d z=%d\n", *x, *y, z);
ret |= 1;
}
return ret;
}
int test_struct_pointer (foo *bar, foo *baz)
{
int ret = 0;
*bar = *baz = foo_init;
if (bar.x != foo_init.x || bar.y != foo_init.y) {
printf ("test_struct: bar={%d %g} foo_init={%d %g}\n",
bar.x, bar.y, foo_init.x, foo_init.y);
ret |= 1;
}
if (baz.x != foo_init.x || baz.y != foo_init.y) {
printf ("test_struct: baz={%d %g} foo_init={%d %g}\n",
baz.x, baz.y, foo_init.x, foo_init.y);
ret |= 1;
}
*bar = *baz = nil;
if (bar.x || baz.x || bar.y || baz.y) {
printf ("test_struct: bar={%d %g} baz={%d %g}\n",
bar.x, bar.y, baz.x, baz.y);
ret |= 1;
}
return ret;
}
int main ()
{
int ret = 0;
ret |= test_simple_global ();
ret |= test_struct_global ();
ret |= test_simple_pointer (&x, &y);
ret |= test_struct_pointer (&bar, &baz);
return ret;
}