summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile171
-rw-r--r--tests/asm-c-connect-1.c13
-rw-r--r--tests/asm-c-connect-2.c11
-rw-r--r--tests/boundtest.c61
-rw-r--r--tests/bug.c75
-rw-r--r--[-rwxr-xr-x]tests/gcctestsuite.sh39
-rw-r--r--tests/libtcc_test.c14
-rw-r--r--tests/libtcc_test_mt.c300
-rw-r--r--tests/misc/c2str.c112
-rw-r--r--tests/misc/tcc_predefs.h111
-rw-r--r--tests/pp/Makefile4
-rw-r--r--tests/tcctest.c874
-rw-r--r--tests/tests2/03_struct.c13
-rw-r--r--tests/tests2/03_struct.expect2
-rw-r--r--tests/tests2/07_function.c5
-rw-r--r--tests/tests2/100_c99array-decls.c34
-rw-r--r--tests/tests2/100_c99array-decls.expect0
-rw-r--r--tests/tests2/101_cleanup.c227
-rw-r--r--tests/tests2/101_cleanup.expect59
-rw-r--r--tests/tests2/102_alignas.c29
-rw-r--r--tests/tests2/102_alignas.expect1
-rw-r--r--tests/tests2/103_implicit_memmove.c20
-rw-r--r--tests/tests2/103_implicit_memmove.expect0
-rw-r--r--tests/tests2/104+_inline.c54
-rw-r--r--tests/tests2/104_inline.c132
-rw-r--r--tests/tests2/104_inline.expect39
-rw-r--r--tests/tests2/105_local_extern.c12
-rw-r--r--tests/tests2/105_local_extern.expect2
-rw-r--r--tests/tests2/106_pthread.c17
-rw-r--r--tests/tests2/106_pthread.expect1
-rw-r--r--tests/tests2/107_stack_safe.c13
-rw-r--r--tests/tests2/107_stack_safe.expect1
-rw-r--r--tests/tests2/108_constructor.c20
-rw-r--r--tests/tests2/108_constructor.expect3
-rw-r--r--tests/tests2/109_float_struct_calling.c24
-rw-r--r--tests/tests2/109_float_struct_calling.expect1
-rw-r--r--tests/tests2/110_average.c27
-rw-r--r--tests/tests2/110_average.expect1
-rw-r--r--tests/tests2/111_conversion.c22
-rw-r--r--tests/tests2/111_conversion.expect1
-rw-r--r--tests/tests2/112_backtrace.c165
-rw-r--r--tests/tests2/112_backtrace.expect142
-rw-r--r--tests/tests2/113_btdll.c43
-rw-r--r--tests/tests2/113_btdll.expect6
-rw-r--r--tests/tests2/114_bound_signal.c110
-rw-r--r--tests/tests2/114_bound_signal.expect2
-rw-r--r--tests/tests2/115_bound_setjmp.c169
-rw-r--r--tests/tests2/115_bound_setjmp.expect0
-rw-r--r--tests/tests2/116_bound_setjmp2.c84
-rw-r--r--tests/tests2/116_bound_setjmp2.expect0
-rw-r--r--tests/tests2/117_gcc_test.c158
-rw-r--r--tests/tests2/117_gcc_test.expect0
-rw-r--r--tests/tests2/11_precedence.c3
-rw-r--r--tests/tests2/22_floating_point.c13
-rw-r--r--tests/tests2/33_ternary_op.c67
-rw-r--r--tests/tests2/33_ternary_op.expect2
-rw-r--r--tests/tests2/46_grep.c4
-rw-r--r--tests/tests2/60_errors_and_warnings.c298
-rw-r--r--tests/tests2/60_errors_and_warnings.expect136
-rw-r--r--tests/tests2/61_integers.c70
-rw-r--r--tests/tests2/61_integers.expect56
-rw-r--r--tests/tests2/73_arm64.c11
-rw-r--r--tests/tests2/81_types.c12
-rw-r--r--tests/tests2/82_attribs_position.c48
-rw-r--r--tests/tests2/82_attribs_position.expect2
-rw-r--r--tests/tests2/85_asm-outside-function.c8
-rw-r--r--tests/tests2/87_dead_code.c33
-rw-r--r--tests/tests2/87_dead_code.expect5
-rw-r--r--tests/tests2/88_codeopt.c3
-rw-r--r--tests/tests2/90_struct-init.c20
-rw-r--r--tests/tests2/90_struct-init.expect5
-rw-r--r--tests/tests2/92_enum_bitfield.c1
-rw-r--r--tests/tests2/94_generic.c51
-rw-r--r--tests/tests2/94_generic.expect3
-rw-r--r--tests/tests2/95_bitfields.c23
-rw-r--r--tests/tests2/95_bitfields.expect24
-rw-r--r--tests/tests2/95_bitfields_ms.expect24
-rw-r--r--tests/tests2/96_nodata_wanted.c24
-rw-r--r--tests/tests2/96_nodata_wanted.expect5
-rw-r--r--tests/tests2/98_al_ax_extend.c2
-rw-r--r--tests/tests2/99_fastcall.c2
-rw-r--r--tests/tests2/Makefile76
82 files changed, 4018 insertions, 437 deletions
diff --git a/tests/Makefile b/tests/Makefile
index 5f6777d..0b74fbc 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -12,6 +12,7 @@ TESTS = \
hello-exe \
hello-run \
libtest \
+ libtest_mt \
test3 \
memtest \
dlltest \
@@ -22,21 +23,30 @@ TESTS = \
tests2-dir \
pp-dir
-BTESTS = test1b test3b btest
-
-# test4 -- problem with -static
+BTESTS = btest test1b
+# test4_static -- Not all relocation types are implemented yet.
# asmtest / asmtest2 -- minor differences with gcc
-# btest -- works on i386 (including win32)
-# bounds-checking is supported only on i386
-ifneq ($(ARCH),i386)
- TESTS := $(filter-out $(BTESTS),$(TESTS))
+# bounds-checking is supported on i386 and x86_64 on linux and windows
+ifeq (-$(CONFIG_musl)-, --)
+ifeq ($(ARCH),i386)
+ TESTS += $(BTESTS)
+endif
+ifeq ($(ARCH),x86_64)
+ TESTS += $(BTESTS)
+endif
+ifeq ($(ARCH),arm)
+ TESTS += $(BTESTS)
+endif
+ifeq ($(ARCH),arm64)
+ TESTS += $(BTESTS)
endif
-ifdef CONFIG_WIN32
- TESTS := $(filter-out $(BTESTS),$(TESTS))
+ifeq ($(ARCH),riscv64)
+ TESTS += $(BTESTS)
endif
-ifdef CONFIG_OSX # -run only
- TESTS := hello-run libtest tests2-dir pp-dir
+endif
+ifdef CONFIG_OSX # some don't work yet
+ TESTS := $(filter-out dlltest, $(TESTS))
endif
ifeq (,$(filter arm64 i386 x86_64,$(ARCH)))
TESTS := $(filter-out vla_test-run,$(TESTS))
@@ -47,19 +57,42 @@ endif
ifeq (,$(filter i386 x86_64,$(ARCH)))
TESTS := $(filter-out dlltest asm-c-connect-test,$(TESTS))
endif
-ifndef CONFIG_cross
- TESTS := $(filter-out cross-%,$(TESTS))
-endif
ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll
- PATH := $(CURDIR)/$(TOP)$(if $(findstring :\,$(PATH)),;,:)$(PATH)
+ PATH := $(CURDIR)/$(TOP)$(if $(findstring ;,$(PATH)),;,:)$(PATH)
+endif
+
+ifdef CONFIG_OSX
+LIBS += $(LINK_LIBTCC)
+endif
+
+
+ifeq ($(ARCH),arm)
+# tcctest refers to the alignment of functions, and with thumb mode
+# the low bit of code addresses selects the mode, so the "alignment"
+# of functions via bit masking comes out as 1. Just disable thumb.
+test.ref: CFLAGS+=-marm
+endif
+ifeq ($(ARCH),i386)
+# tcctest.c:get_asm_string uses a construct that is checked too strictly
+# by GCC in 32bit mode when PIC is enabled.
+test.ref: CFLAGS+=-fno-PIC -fno-PIE
+endif
+ifeq ($(CC_NAME),msvc)
+test.ref abitest : CC = gcc
endif
RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
DISAS = objdump -d
+ifdef CONFIG_OSX
+DUMPTCC = (set -x; $(TOP)/tcc -vv; otool -L $(TOP)/tcc; exit 1)
+else
DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1)
+endif
-all test : clean-s $(TESTS)
+all test :
+ @$(MAKE) --no-print-directory -s clean
+ @$(MAKE) --no-print-directory -s -r $(TESTS)
hello-exe: ../examples/ex1.c
@echo ------------ $@ ------------
@@ -69,13 +102,16 @@ hello-run: ../examples/ex1.c
@echo ------------ $@ ------------
$(TCC) -run $< || $(DUMPTCC)
-libtest: libtcc_test$(EXESUF)
+libtes%: libtcc_tes%$(EXESUF)
@echo ------------ $@ ------------
- ./libtcc_test$(EXESUF) $(TCCFLAGS)
+ ./libtcc_tes$*$(EXESUF) $(TOPSRC)/tcc.c $(TCCFLAGS) $(NATIVE_DEFINES)
libtcc_test$(EXESUF): libtcc_test.c $(LIBTCC)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+libtcc_test_mt$(EXESUF): libtcc_test_mt.c $(LIBTCC)
+ $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+
%-dir:
@echo ------------ $@ ------------
$(MAKE) -k -C $*
@@ -88,22 +124,24 @@ test.ref: tcctest.c
# auto test
test1 test1b: tcctest.c test.ref
@echo ------------ $@ ------------
- $(TCC) -run $< > test.out1
- @diff -u test.ref test.out1 && echo "Auto Test OK"
+ $(TCC) $(RUN_TCC) -w -run $< > test.out1
+ @diff -u test.ref test.out1 && echo "$(AUTO_TEST) OK"
# iterated test2 (compile tcc then compile tcctest.c !)
test2 test2b: tcctest.c test.ref
@echo ------------ $@ ------------
- $(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2
- @diff -u test.ref test.out2 && echo "Auto Test2 OK"
+ $(TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out2
+ @diff -u test.ref test.out2 && echo "$(AUTO_TEST)2 OK"
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
test3 test3b: tcctest.c test.ref
@echo ------------ $@ ------------
- $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3
- @diff -u test.ref test.out3 && echo "Auto Test3 OK"
+ $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -w -run $< > test.out3
+ @diff -u test.ref test.out3 && echo "$(AUTO_TEST)3 OK"
-test%b : TCCFLAGS += -b
+AUTO_TEST = Auto Test
+test%b : TCCFLAGS += -b -bt1
+test%b : AUTO_TEST = Auto Bound-Test
# binary output test
test4: tcctest.c test.ref
@@ -112,19 +150,22 @@ test4: tcctest.c test.ref
$(TCC) -c -o tcctest3.o $<
$(TCC) -o tcctest3 tcctest3.o
./tcctest3 > test3.out
- @if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi
+ @if diff -u test.ref test3.out ; then echo "Object $(AUTO_TEST) OK"; fi
# dynamic output
$(TCC) -o tcctest1 $<
./tcctest1 > test1.out
- @if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
+ @if diff -u test.ref test1.out ; then echo "Dynamic $(AUTO_TEST) OK"; fi
# dynamic output + bound check
$(TCC) -b -o tcctest4 $<
./tcctest4 > test4.out
- @if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
-# static output
+ @if diff -u test.ref test4.out ; then echo "BCheck $(AUTO_TEST) OK"; fi
+
+test4_static: tcctest.c test.ref
+ @echo ------------ $@ ------------
+# static output.
$(TCC) -static -o tcctest2 $<
./tcctest2 > test2.out
- @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
+ @if diff -u test.ref test2.out ; then echo "Static $(AUTO_TEST) OK"; fi
# use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them
dlltest:
@@ -145,32 +186,30 @@ memtest:
@echo ------------ $@ ------------
$(CC) $(CFLAGS) $(NATIVE_DEFINES) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF)
./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) $(TOPSRC)/tcc.c $(LIBS)
- ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) $(TOPSRC)/tests/tcctest.c
-
+ ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) -w $(TOPSRC)/tests/tcctest.c
+ @echo OK
# memory and bound check auto test
-BOUNDS_OK = 1 4 8 10 14
-BOUNDS_FAIL= 2 5 7 9 11 12 13 15
+BOUNDS_OK = 1 4 8 10 14 16
+BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17 18
btest: boundtest.c
@echo ------------ $@ ------------
@for i in $(BOUNDS_OK); do \
- echo ; echo --- boundtest $$i ---; \
- if $(TCC) -b -run $< $$i ; then \
- echo succeeded as expected; \
+ if $(TCC) -b -run $< $$i >/dev/null 2>&1 ; then \
+ echo "Test $$i succeeded as expected" ; \
else\
- echo Failed positive test $$i ; exit 1 ; \
+ echo "Failed positive test $$i" ; exit 1 ; \
fi ;\
done ;\
for i in $(BOUNDS_FAIL); do \
- echo ; echo --- boundtest $$i ---; \
- if $(TCC) -b -run $< $$i ; then \
- echo Failed negative test $$i ; exit 1 ;\
+ if $(TCC) -b -bt1 -run $< $$i >/dev/null 2>&1 ; then \
+ echo "Failed negative test $$i" ; exit 1 ;\
else\
- echo failed as expected; \
+ echo "Test $$i failed as expected" ; \
fi ;\
done ;\
- echo; echo Bound test OK
+ echo Bound test OK
# speed test
speedtest: ex2 ex3
@@ -181,6 +220,7 @@ speedtest: ex2 ex3
time $(TCC) -run $(TOPSRC)/examples/ex3.c 35
weaktest: tcctest.c test.ref
+ @echo ------------ $@ ------------
$(TCC) -c $< -o weaktest.tcc.o
$(CC) -c $< -o weaktest.gcc.o $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt
@@ -206,22 +246,19 @@ asmtest2: MAYBE_RUN_TCC = $(RUN_TCC)
# Check that code generated by libtcc is binary compatible with
# that generated by CC
-abitest-cc$(EXESUF): abitest.c $(LIBTCC)
+abitest-cc.exe: abitest.c $(LIBTCC)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) -w
-abitest-tcc$(EXESUF): abitest.c libtcc.c
+abitest-tcc.exe: abitest.c libtcc.c
$(TCC) -o $@ $^ $(NATIVE_DEFINES) $(LIBS)
-ABITESTS := abitest-cc$(EXESUF)
-ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
- ABITESTS += abitest-tcc$(EXESUF)
-endif
-
-abitest: $(ABITESTS)
+abitest-% : abitest-%.exe
@echo ------------ $@ ------------
- ./abitest-cc$(EXESUF) $(TCCFLAGS)
+ ./$< $(TCCFLAGS)
+
+abitest: abitest-cc
ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
- ./abitest-tcc$(EXESUF) $(TCCFLAGS)
+abitest: abitest-tcc
endif
vla_test$(EXESUF): vla_test.c
@@ -244,21 +281,18 @@ asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF)
@echo ------------ $@ ------------
./asm-c-connect$(EXESUF) > asm-c-connect.out1 && cat asm-c-connect.out1
./asm-c-connect-sep$(EXESUF) > asm-c-connect.out2 && cat asm-c-connect.out2
- @diff -u asm-c-connect.out1 asm-c-connect.out2 && echo "ok"
+ @diff -u asm-c-connect.out1 asm-c-connect.out2 || (echo "error"; exit 1)
+
+TCC_YY = $(foreach T,$(TCC_X),$(if $(wildcard $(TOP)/$T-tcc$(EXESUF)),$T))
cross-test :
+ $(if $(strip $(TCC_YY)),\
+ $(MAKE) $(foreach T,$(TCC_YY),cross-$T.test) --no-print-directory,:)
+
+cross-%.test :
@echo ------------ $@ ------------
- $(TOP)/i386-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
- $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok"
- $(TOP)/x86_64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
- $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok"
- $(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
- $(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/examples/ex3.c && echo "ok"
- $(TOP)/arm64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
- $(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
- $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
- $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
- $(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
+ $(TOP)/$*-tcc$(EXESUF) -v $(TCCFLAGS-$(if $(findstring win,$*),win,unx))\
+ -c $(TOPSRC)/examples/ex3.c
# targets for development
%.bin: %.c tcc
@@ -279,11 +313,8 @@ cache: tcc_g
clean:
rm -f *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc *.gcc
rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test vla_test tcctest[1234]
- rm -f asm-c-connect$(EXESUF)
- rm -f ex? tcc_g weaktest.*.txt *.def
+ rm -f asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF)
+ rm -f ex? tcc_g weaktest.*.txt *.def *.pdb *.obj libtcc_test_mt
@$(MAKE) -C tests2 $@
@$(MAKE) -C pp $@
-# silent clean, used before running tests
-clean-s:
- @$(MAKE) -s --no-print-directory clean
diff --git a/tests/asm-c-connect-1.c b/tests/asm-c-connect-1.c
index 8a28d78..d79270d 100644
--- a/tests/asm-c-connect-1.c
+++ b/tests/asm-c-connect-1.c
@@ -1,12 +1,19 @@
#include <stdio.h>
-#if defined _WIN32 && !defined __TINYC__
+#if (defined _WIN32 || defined __APPLE__) && (!defined __TINYC__ || defined __leading_underscore)
# define _ "_"
#else
# define _
#endif
-static int x1_c(void)
+#ifdef __clang__
+/* clang needs some help tp not throw functions away even at -O0 */
+#define __USED __attribute__((__used__))
+#else
+#define __USED
+#endif
+
+static int __USED x1_c (void)
{
printf(" x1");
return 1;
@@ -37,7 +44,7 @@ int main(int argc, char *argv[])
}
static
-int x2(void)
+int __USED x2(void)
{
printf(" x2");
return 2;
diff --git a/tests/asm-c-connect-2.c b/tests/asm-c-connect-2.c
index 3440b40..e2b4b59 100644
--- a/tests/asm-c-connect-2.c
+++ b/tests/asm-c-connect-2.c
@@ -1,11 +1,18 @@
#include <stdio.h>
-#if defined _WIN32 && !defined __TINYC__
+#if (defined _WIN32 || defined __APPLE__) && (!defined __TINYC__ || defined __leading_underscore)
# define _ "_"
#else
# define _
#endif
+#ifdef __clang__
+/* clang needs some help tp not throw functions away even at -O0 */
+#define __USED __attribute__((__used__))
+#else
+#define __USED
+#endif
+
int x3(void)
{
printf(" x3");
@@ -30,7 +37,7 @@ void callx5_again(void)
asm("call "_"x6");
}
-static void x6()
+static void __USED x6()
{
printf(" x6-2");
}
diff --git a/tests/boundtest.c b/tests/boundtest.c
index 15bffb4..0d83395 100644
--- a/tests/boundtest.c
+++ b/tests/boundtest.c
@@ -50,15 +50,12 @@ int test4(void)
int i, sum = 0;
int *tab4;
- fprintf(stderr, "%s start\n", __FUNCTION__);
-
tab4 = malloc(20 * sizeof(int));
for(i=0;i<20;i++) {
sum += tab4[i];
}
free(tab4);
- fprintf(stderr, "%s end\n", __FUNCTION__);
return sum;
}
@@ -68,20 +65,16 @@ int test5(void)
int i, sum = 0;
int *tab4;
- fprintf(stderr, "%s start\n", __FUNCTION__);
-
tab4 = malloc(20 * sizeof(int));
for(i=0;i<21;i++) {
sum += tab4[i];
}
free(tab4);
- fprintf(stderr, "%s end\n", __FUNCTION__);
return sum;
}
/* error */
-/* XXX: currently: bug */
int test6(void)
{
int i, sum = 0;
@@ -176,21 +169,34 @@ int test13(void)
return strlen(tab);
}
+#if defined __i386__ || defined __x86_64__
+#define allocf(x)
+#else
+#define alloca(x) malloc(x)
+#define allocf(x) free(x)
+#endif
+
int test14(void)
{
char *p = alloca(TAB_SIZE);
+ size_t ret;
memset(p, 'a', TAB_SIZE);
p[TAB_SIZE-1] = 0;
- return strlen(p);
+ ret = strlen(p);
+ allocf(p);
+ return ret;
}
/* error */
int test15(void)
{
char *p = alloca(TAB_SIZE-1);
+ size_t ret;
memset(p, 'a', TAB_SIZE);
p[TAB_SIZE-1] = 0;
- return strlen(p);
+ ret = strlen(p);
+ allocf(p);
+ return ret;
}
/* ok */
@@ -199,16 +205,14 @@ int test16()
char *demo = "This is only a test.";
char *p;
- fprintf(stderr, "%s start\n", __FUNCTION__);
-
p = alloca(16);
strcpy(p,"12345678901234");
- printf("alloca: p is %s\n", p);
+ allocf(p);
/* Test alloca embedded in a larger expression */
- printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) );
+ printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)+1),demo) );
- fprintf(stderr, "%s end\n", __FUNCTION__);
+ return 0;
}
/* error */
@@ -217,16 +221,24 @@ int test17()
char *demo = "This is only a test.";
char *p;
- fprintf(stderr, "%s start\n", __FUNCTION__);
-
p = alloca(16);
strcpy(p,"12345678901234");
- printf("alloca: p is %s\n", p);
+ allocf(p);
/* Test alloca embedded in a larger expression */
- printf("alloca: %s\n", strcpy(alloca(strlen(demo)),demo) );
+ printf("alloca : %s : %s\n", p, strcpy(alloca(strlen(demo)),demo) );
+
+ return 0;
+}
- fprintf(stderr, "%s end\n", __FUNCTION__);
+int test18(void)
+{
+ int i, sum = 0, n = TAB_SIZE;
+ int tab[n];
+ for(i=0;i<TAB_SIZE+1;i++) {
+ sum += tab[i];
+ }
+ return sum;
}
int (*table_test[])(void) = {
@@ -247,14 +259,25 @@ int (*table_test[])(void) = {
test15,
test16,
test17,
+ test18
};
int main(int argc, char **argv)
{
+ int i;
+ char *cp;
int index;
int (*ftest)(void);
int index_max = sizeof(table_test)/sizeof(table_test[0]);
+ /* check bounds checking main arg */
+ for (i = 0; i < argc; i++) {
+ cp = argv[i];
+ while (*cp) {
+ cp++;
+ }
+ }
+
if (argc < 2) {
printf(
"test TCC bound checking system\n"
diff --git a/tests/bug.c b/tests/bug.c
new file mode 100644
index 0000000..7ec4410
--- /dev/null
+++ b/tests/bug.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+void tst1(void)
+{
+ /* problem in gen_cast. Should mask unsigned types */
+ signed char c = (signed char) 0xffffffff;
+ int r = (unsigned short) c ^ (signed char) 0x99999999;
+ if (r != 0xffff0066) printf ("%x\n", r);
+}
+
+typedef struct{double x,y;}p;
+
+void tst2(int n,...)
+{
+ /* va_arg for struct double does not work on some targets */
+ int i;
+ va_list args;
+ va_start(args,n);
+ for (i = 0; i < n; i++) {
+ p v = va_arg(args,p);
+ if (v.x != 1 || v.y != 2) printf("%g %g\n", v.x, v.y);
+ }
+ va_end(args);
+}
+
+void tst3(void)
+{
+ /* Should VT_SYM be checked for TOK_builtin_constant_p */
+ int r = __builtin_constant_p("c");
+ if (r == 0) printf("%d\n",r);
+}
+
+int compile_errors(void)
+{
+#if TEST == 1
+ {
+ /* Not constant */
+ static int i = (&"Foobar"[1] - &"Foobar"[0]);
+ }
+#endif
+#if TEST == 2
+ {
+ /* Not constant */
+ struct{int c;}v;
+ static long i=((char*)&(v.c)-(char*)&v);
+ }
+#endif
+#if TEST == 3
+ {
+ /* Not constant */
+ static const short ar[] = { &&l1 - &&l1, &&l2 - &&l1 };
+ void *p = &&l1 + ar[0];
+ goto *p;
+ l1: return 1;
+ l2: return 2;
+ }
+#endif
+#if TEST == 4
+ {
+ /* Only integer allowed */
+ __builtin_return_address(0 + 1) != NULL;
+ }
+#endif
+ return 0;
+}
+
+int
+main(void)
+{
+ p v = { 1, 2};
+ tst1();
+ tst2(1, v);
+ tst3();
+}
diff --git a/tests/gcctestsuite.sh b/tests/gcctestsuite.sh
index f3cc538..2be274c 100755..100644
--- a/tests/gcctestsuite.sh
+++ b/tests/gcctestsuite.sh
@@ -1,33 +1,48 @@
#!/bin/sh
TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture
-TCC="./tcc -B. -I. -DNO_TRAMPOLINES"
-rm -f tcc.sum tcc.log
+TCC="./tcc -B. -I. -DNO_TRAMPOLINES"
+rm -f tcc.sum tcc.fail
+nb_ok="0"
nb_failed="0"
+nb_exe_failed="0"
for src in $TESTSUITE_PATH/compile/*.c ; do
- echo $TCC -o /tmp/test.o -c $src
- $TCC -o /tmp/test.o -c $src >> tcc.log 2>&1
+ echo $TCC -o /tmp/tst.o -c $src
+ $TCC -o /tmp/tst.o -c $src >> tcc.fail 2>&1
if [ "$?" = "0" ] ; then
- result="PASS"
+ result="PASS"
+ nb_ok=$(( $nb_ok + 1 ))
else
- result="FAIL"
- nb_failed=$(( $nb_failed + 1 ))
+ result="FAIL"
+ nb_failed=$(( $nb_failed + 1 ))
fi
echo "$result: $src" >> tcc.sum
done
for src in $TESTSUITE_PATH/execute/*.c ; do
- echo $TCC $src
- $TCC $src >> tcc.log 2>&1
+ echo $TCC $src -o /tmp/tst -lm
+ $TCC $src -o /tmp/tst -lm >> tcc.fail 2>&1
if [ "$?" = "0" ] ; then
- result="PASS"
+ result="PASS"
+ if /tmp/tst >> tcc.fail 2>&1
+ then
+ result="PASS"
+ nb_ok=$(( $nb_ok + 1 ))
+ else
+ result="FAILEXE"
+ nb_exe_failed=$(( $nb_exe_failed + 1 ))
+ fi
else
- result="FAIL"
- nb_failed=$(( $nb_failed + 1 ))
+ result="FAIL"
+ nb_failed=$(( $nb_failed + 1 ))
fi
echo "$result: $src" >> tcc.sum
done
+echo "$nb_ok test(s) ok." >> tcc.sum
+echo "$nb_ok test(s) ok."
echo "$nb_failed test(s) failed." >> tcc.sum
echo "$nb_failed test(s) failed."
+echo "$nb_exe_failed test(s) exe failed." >> tcc.sum
+echo "$nb_exe_failed test(s) exe failed."
diff --git a/tests/libtcc_test.c b/tests/libtcc_test.c
index 480d314..d21c7fe 100644
--- a/tests/libtcc_test.c
+++ b/tests/libtcc_test.c
@@ -6,9 +6,15 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include "libtcc.h"
+void handle_error(void *opaque, const char *msg)
+{
+ fprintf(opaque, "%s\n", msg);
+}
+
/* this function is called by the generated code */
int add(int a, int b)
{
@@ -53,6 +59,14 @@ int main(int argc, char **argv)
exit(1);
}
+ assert(tcc_get_error_func(s) == NULL);
+ assert(tcc_get_error_opaque(s) == NULL);
+
+ tcc_set_error_func(s, stderr, handle_error);
+
+ assert(tcc_get_error_func(s) == handle_error);
+ assert(tcc_get_error_opaque(s) == stderr);
+
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
for (i = 1; i < argc; ++i) {
char *a = argv[i];
diff --git a/tests/libtcc_test_mt.c b/tests/libtcc_test_mt.c
new file mode 100644
index 0000000..b17e8de
--- /dev/null
+++ b/tests/libtcc_test_mt.c
@@ -0,0 +1,300 @@
+/*
+ * Multi-thread Test for libtcc
+ */
+
+#ifndef FIB
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "libtcc.h"
+
+#define M 20 /* number of states */
+#define F(n) (n % 20 + 2) /* fib argument */
+
+#ifdef _WIN32
+#include <windows.h>
+#define TF_TYPE(func, param) DWORD WINAPI func(void *param)
+typedef TF_TYPE(ThreadFunc, x);
+HANDLE hh[M];
+void create_thread(ThreadFunc f, int n)
+{
+ DWORD tid;
+ hh[n] = CreateThread(NULL, 0, f, (void*)(size_t)n, 0, &tid);
+}
+void wait_threads(int n)
+{
+ WaitForMultipleObjects(n, hh, TRUE, INFINITE);
+ while (n)
+ CloseHandle(hh[--n]);
+}
+void sleep_ms(unsigned n)
+{
+ Sleep(n);
+}
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#include <pthread.h>
+#define TF_TYPE(func, param) void* func(void *param)
+typedef TF_TYPE(ThreadFunc, x);
+pthread_t hh[M];
+void create_thread(ThreadFunc f, int n)
+{
+ pthread_create(&hh[n], NULL, f, (void*)(size_t)n);
+}
+void wait_threads(int n)
+{
+ while (n)
+ pthread_join(hh[--n], NULL);
+
+}
+void sleep_ms(unsigned n)
+{
+ usleep(n * 1000);
+}
+#endif
+
+void handle_error(void *opaque, const char *msg)
+{
+ fprintf(opaque, "%s\n", msg);
+}
+
+/* this function is called by the generated code */
+int add(int a, int b)
+{
+ return a + b;
+}
+
+#define _str(s) #s
+#define str(s) _str(s)
+/* as a trick, prepend #line directive for better error/warning messages */
+#define PROG(lbl) \
+ char lbl[] = "#line " str(__LINE__) " " str(__FILE__) "\n\n"
+
+PROG(my_program)
+"#include <tcclib.h>\n" /* include the "Simple libc header for TCC" */
+"int add(int a, int b);\n"
+"int fib(int n)\n"
+"{\n"
+" if (n <= 2)\n"
+" return 1;\n"
+" else\n"
+" return add(fib(n-1),fib(n-2));\n"
+"}\n"
+"\n"
+"int foo(int n)\n"
+"{\n"
+" printf(\" %d\", fib(n));\n"
+" return 0;\n"
+"# warning is this the correct file:line...\n"
+"}\n";
+
+int g_argc; char **g_argv;
+
+void parse_args(TCCState *s)
+{
+ int i;
+ /* if tcclib.h and libtcc1.a are not installed, where can we find them */
+ for (i = 1; i < g_argc; ++i) {
+ char *a = g_argv[i];
+ if (a[0] == '-') {
+ if (a[1] == 'B')
+ tcc_set_lib_path(s, a+2);
+ else if (a[1] == 'I')
+ tcc_add_include_path(s, a+2);
+ else if (a[1] == 'L')
+ tcc_add_library_path(s, a+2);
+ else if (a[1] == 'D')
+ tcc_define_symbol(s, a+2, NULL);
+ }
+ }
+}
+
+TCCState *new_state(int w)
+{
+ TCCState *s = tcc_new();
+ if (!s) {
+ fprintf(stderr, __FILE__ ": could not create tcc state\n");
+ exit(1);
+ }
+ tcc_set_error_func(s, stdout, handle_error);
+ parse_args(s);
+ if (!w) tcc_set_options(s, "-w");
+ tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
+ return s;
+}
+
+void *reloc_state(TCCState *s, const char *entry)
+{
+ void *func;
+ tcc_add_symbol(s, "add", add);
+ if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
+ fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
+ return NULL;
+ }
+ func = tcc_get_symbol(s, entry);
+ if (!func)
+ fprintf(stderr, __FILE__ ": could not get entry symbol.\n");
+ return func;
+}
+
+/* work with several states at the same time */
+int state_test(void)
+{
+ TCCState *s[M];
+ int (*func[M])(int);
+ int n;
+
+ for (n = 0; n < M + 4; ++n) {
+ unsigned a = n, b = n - 1, c = n - 2, d = n - 3, e = n - 4;
+ if (a < M)
+ s[a] = new_state(0);
+ if (b < M)
+ if (tcc_compile_string(s[b], my_program) == -1)
+ break;
+ if (c < M)
+ func[c] = reloc_state(s[c], "foo");
+ if (d < M && func[d])
+ func[d](F(d));
+ if (e < M)
+ tcc_delete(s[e]);
+ }
+ return 0;
+}
+
+/* simple compilation in threads */
+TF_TYPE(thread_test_simple, vn)
+{
+ TCCState *s;
+ int (*func)(int);
+ int ret;
+ int n = (size_t)vn;
+
+ s = new_state(0);
+ sleep_ms(1);
+ ret = tcc_compile_string(s, my_program);
+ sleep_ms(1);
+ if (ret >= 0) {
+ func = reloc_state(s, "foo");
+ if (func)
+ func(F(n));
+ }
+ tcc_delete(s);
+ return 0;
+}
+
+/* more complex compilation in threads */
+TF_TYPE(thread_test_complex, vn)
+{
+ TCCState *s;
+ int ret;
+ int n = (size_t)vn;
+ char *argv[30], b[10];
+ int argc = 0, i;
+
+ sprintf(b, "%d", F(n));
+
+ for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
+#if 0
+ argv[argc++] = "-run";
+ for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
+#endif
+ argv[argc++] = "-DFIB";
+ argv[argc++] = "-run";
+ argv[argc++] = __FILE__;
+ argv[argc++] = b;
+ argv[argc] = NULL;
+
+ s = new_state(1);
+ sleep_ms(2);
+ ret = tcc_add_file(s, argv[0]);
+ sleep_ms(3);
+ if (ret < 0)
+ exit(1);
+ tcc_run(s, argc, argv);
+ tcc_delete(s);
+ fflush(stdout);
+ return 0;
+}
+
+void time_tcc(int n, const char *src)
+{
+ TCCState *s;
+ int ret;
+ while (--n >= 0) {
+ s = new_state(1);
+ ret = tcc_add_file(s, src);
+ tcc_delete(s);
+ if (ret < 0)
+ exit(1);
+ }
+}
+
+static unsigned getclock_ms(void)
+{
+#ifdef _WIN32
+ return GetTickCount();
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ int n;
+ unsigned t;
+
+ g_argc = argc;
+ g_argv = argv;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: libtcc_test_mt tcc.c <options>\n");
+ return 1;
+ }
+
+#if 1
+ printf("running fib with mixed calls\n "), fflush(stdout);
+ t = getclock_ms();
+ state_test();
+ printf("\n (%u ms)\n", getclock_ms() - t);
+#endif
+#if 1
+ printf("running fib in threads\n "), fflush(stdout);
+ t = getclock_ms();
+ for (n = 0; n < M; ++n)
+ create_thread(thread_test_simple, n);
+ wait_threads(n);
+ printf("\n (%u ms)\n", getclock_ms() - t);
+#endif
+#if 1
+ printf("running tcc.c in threads to run fib\n"), fflush(stdout);
+ t = getclock_ms();
+ for (n = 0; n < M; ++n)
+ create_thread(thread_test_complex, n);
+ wait_threads(n);
+ printf("\n (%u ms)\n", getclock_ms() - t);
+#endif
+#if 1
+ printf("compiling tcc.c 10 times\n"), fflush(stdout);
+ t = getclock_ms();
+ time_tcc(10, argv[1]);
+ printf(" (%u ms)\n", getclock_ms() - t), fflush(stdout);
+#endif
+ return 0;
+}
+
+#else
+#include <tcclib.h>
+int fib(n)
+{
+ return (n <= 2) ? 1 : fib(n-1) + fib(n-2);
+}
+
+int main(int argc, char **argv)
+{
+ printf(" %d", fib(atoi(argv[1]), 2));
+ return 0;
+}
+#endif
diff --git a/tests/misc/c2str.c b/tests/misc/c2str.c
new file mode 100644
index 0000000..01d18db
--- /dev/null
+++ b/tests/misc/c2str.c
@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <string.h>
+
+int isid(int c)
+{
+ return (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == '_';
+}
+
+int isspc(int c)
+{
+ return c == ' ' || c == '\t';
+}
+
+int main(int argc, char **argv)
+{
+ char l[1000], *p, l2[1000], *q;
+ FILE *fp, *op;
+ int c, e, f;
+
+ if (argc < 3)
+ return 1;
+
+ fp = fopen(argv[1], "rb");
+ op = fopen(argv[2], "wb");
+ if (!fp || !op) {
+ fprintf(stderr, "c2str: file error\n");
+ return 1;
+ }
+
+ for (;;) {
+ p = l;
+ append:
+ if (fgets(p, sizeof l - (p - l), fp)) {
+ p = strchr(p, 0);
+ while (p > l && p[-1] == '\n')
+ --p;
+ *p = 0;
+ } else if (p == l)
+ break;
+ if (p > l && p[-1] == '\\') {
+ --p;
+ goto append;
+ }
+
+ if (l[0] == 0)
+ continue;
+ p = l, q = l2, f = e = 0;
+ while (*p && isspc(*p))
+ ++p, ++f;
+
+ if (f < 4) {
+ do {
+ static const char *sr[] = {
+ "__x86_64__", "TCC_TARGET_X86_64",
+ "_WIN64", "TCC_TARGET_PE",
+ "_WIN32", "TCC_TARGET_PE",
+ "__arm__", "TCC_TARGET_ARM",
+ "__aarch64__", "TCC_TARGET_ARM64",
+ "__riscv", "TCC_TARGET_RISCV64",
+ "__i386__", "TCC_TARGET_I386", 0 };
+ for (f = 0; sr[f]; f += 2) {
+ c = strlen(sr[f]);
+ if (0 == memcmp(p, sr[f], c)) {
+ p += c, ++f;
+ q = strchr(strcpy(q, sr[f]), 0);
+ break;
+ }
+
+ }
+ if (sr[f])
+ continue;
+ } while (!!(*q++ = *p++));
+
+ fprintf(op, "%s\n", l2);
+
+ } else if (*p == '/') {
+ strcpy(q, p);
+ fprintf(op, " %s\n", l2);
+
+ } else {
+ f = 0;
+ for (;;) {
+ c = *p++;
+ if (isspc(c)) {
+ if (q == l2 || isspc(q[-1]))
+ continue;
+ if ((f > 2 || e) || (q[-1] != ')' && *p != '(')) {
+ if (!isid(q[-1]) || !isid(*p))
+ continue;
+ }
+ }
+ if (c == '(')
+ ++e, ++f;
+ if (c == ')')
+ --e, ++f;
+ if (c == '\\' || c == '\"')
+ *q++ = '\\';
+ *q++ = c;
+ if (c == 0)
+ break;
+ }
+ fprintf(op, " \"%s\\n\"\n", l2);
+ }
+ }
+
+ fclose(fp);
+ fclose(op);
+ return 0;
+}
diff --git a/tests/misc/tcc_predefs.h b/tests/misc/tcc_predefs.h
new file mode 100644
index 0000000..bbba425
--- /dev/null
+++ b/tests/misc/tcc_predefs.h
@@ -0,0 +1,111 @@
+#if defined __x86_64__
+#ifndef _WIN64
+ /* GCC compatible definition of va_list. */
+ /* This should be in sync with the declaration in our lib/libtcc1.c */
+ typedef struct {
+ unsigned gp_offset, fp_offset;
+ union {
+ unsigned overflow_offset;
+ char *overflow_arg_area;
+ };
+ char *reg_save_area;
+ } __builtin_va_list[1];
+
+ void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
+ #define __builtin_va_start(ap, last) \
+ (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
+ #define __builtin_va_arg(ap, t) \
+ (*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t))))
+ #define __builtin_va_copy(dest, src) (*(dest) = *(src))
+
+#else /* _WIN64 */
+ typedef char *__builtin_va_list;
+ #define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
+ ? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
+#endif
+
+#elif defined __arm__
+ typedef char *__builtin_va_list;
+ #define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
+ #define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
+ & ~(_tcc_alignof(type) - 1))
+ #define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
+ #define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
+ &~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
+
+#elif defined __aarch64__
+ typedef struct {
+ void *__stack, *__gr_top, *__vr_top;
+ int __gr_offs, __vr_offs;
+ } __builtin_va_list;
+
+#elif defined __riscv
+ typedef char *__builtin_va_list;
+ #define __va_reg_size (__riscv_xlen >> 3)
+ #define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
+ & -(__alignof__(type)))
+ #define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
+
+#else /* __i386__ */
+ typedef char *__builtin_va_list;
+ #define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
+ #define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))
+
+#endif
+ #define __builtin_va_end(ap) (void)(ap)
+ #ifndef __builtin_va_copy
+ # define __builtin_va_copy(dest, src) (dest) = (src)
+ #endif
+
+
+ /* TCC BBUILTIN AND BOUNDS ALIASES */
+ #ifdef __BOUNDS_CHECKING_ON
+ # define __BUILTIN(ret,name,params) \
+ ret __builtin_##name params __attribute__((alias("__bound_" #name)));
+ # define __BOUND(ret,name,params) \
+ ret name params __attribute__((alias("__bound_" #name)));
+ #else
+ # define __BUILTIN(ret,name,params) \
+ ret __builtin_##name params __attribute__((alias(#name)));
+ # define __BOUND(ret,name,params)
+ #endif
+ # define __BOTH(ret,name,params) \
+ __BUILTIN(ret,name,params) __BOUND(ret,name,params)
+
+ __BOTH(void*, memcpy, (void *, const void*, __SIZE_TYPE__))
+ __BOTH(void*, memmove, (void *, const void*, __SIZE_TYPE__))
+ __BOTH(void*, memset, (void *, int, __SIZE_TYPE__))
+ __BOTH(int, memcmp, (const void *, const void*, __SIZE_TYPE__))
+ __BOTH(__SIZE_TYPE__, strlen, (const char *))
+ __BOTH(char*, strcpy, (char *, const char *))
+ __BOTH(char*, strncpy, (char *, const char*, __SIZE_TYPE__))
+ __BOTH(int, strcmp, (const char*, const char*))
+ __BOTH(int, strncmp, (const char*, const char*, __SIZE_TYPE__))
+ __BOTH(char*, strcat, (char*, const char*))
+ __BOTH(char*, strchr, (const char*, int))
+ __BOTH(char*, strdup, (const char*))
+
+#ifdef _WIN32
+ #define __MAYBE_REDIR __BOTH
+#else // HAVE MALLOC_REDIR
+ #define __MAYBE_REDIR __BUILTIN
+#endif
+ __MAYBE_REDIR(void*, malloc, (__SIZE_TYPE__))
+ __MAYBE_REDIR(void*, realloc, (void *, __SIZE_TYPE__))
+ __MAYBE_REDIR(void*, calloc, (__SIZE_TYPE__, __SIZE_TYPE__))
+ __MAYBE_REDIR(void*, memalign, (__SIZE_TYPE__, __SIZE_TYPE__))
+ __MAYBE_REDIR(void, free, (void*))
+
+#if defined __i386__ || defined __x86_64__
+ __BOTH(void*, alloca, (__SIZE_TYPE__))
+#endif
+ __BUILTIN(void, abort, (void))
+ __BOUND(int, longjmp, ())
+#ifndef _WIN32
+ __BOUND(void*, mmap, ())
+ __BOUND(void*, munmap, ())
+#endif
+ #undef __BUILTIN
+ #undef __BOUND
+ #undef __BOTH
+ #undef __MAYBE_REDIR
diff --git a/tests/pp/Makefile b/tests/pp/Makefile
index 687aa52..4785db3 100644
--- a/tests/pp/Makefile
+++ b/tests/pp/Makefile
@@ -10,7 +10,7 @@ VPATH = $(SRC)
files = $(patsubst %.$1,%.test,$(notdir $(wildcard $(SRC)/*.$1)))
TESTS = $(call files,c) $(call files,S)
-all test : $(sort $(TESTS))
+all test testspp.all: $(sort $(TESTS))
DIFF_OPTS = -Nu -b -B
@@ -29,6 +29,8 @@ FILTER = 2>&1 | sed 's,$(SRC)/,,g'
diff $(DIFF_OPTS) $(SRC)/$*.expect $*.output \
&& rm -f $*.output
+testspp.%: %.test ;
+
# automatically generate .expect files with gcc:
%.expect: # %.c
gcc -E -P $*.[cS] >$*.expect 2>&1
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 57670be..4ac2cc0 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -3,7 +3,10 @@
*/
#include "config.h"
-#if GCC_MAJOR >= 3
+/* identify the configured reference compiler in use */
+#define CC_gcc 1
+#define CC_clang 2
+#define CC_tcc 3
/* Unfortunately, gcc version < 3 does not handle that! */
#define ALL_ISOC99
@@ -11,9 +14,11 @@
/* only gcc 3 handles _Bool correctly */
#define BOOL_ISOC99
-/* gcc 2.95.3 does not handle correctly CR in strings or after strays */
-#define CORRECT_CR_HANDLING
+/* __VA_ARGS__ and __func__ support */
+#define C99_MACROS
+#ifndef __TINYC__
+typedef __SIZE_TYPE__ uintptr_t;
#endif
#if defined(_WIN32)
@@ -33,12 +38,6 @@
#define LONG_DOUBLE_LITERAL(x) x ## L
#endif
-/* deprecated and no longer supported in gcc 3.3 */
-//#define ACCEPT_CR_IN_STRINGS
-
-/* __VA_ARGS__ and __func__ support */
-#define C99_MACROS
-
/* test various include syntaxes */
#define TCCLIB_INC <tcclib.h>
@@ -64,65 +63,19 @@
#define INC(name) <tests/name.h>
#define funnyname 42test.h
#define incdir tests/
+#ifdef __clang__
+/* clang's preprocessor is broken in this regard and adds spaces
+ to the tokens 'incdir' and 'funnyname' when expanding */
+#define incname <tests/42test.h>
+#else
#define incname < incdir funnyname >
+#endif
#define __stringify(x) #x
#define stringify(x) __stringify(x)
#include INC(42test)
#include incname
#include stringify(funnyname)
-void intdiv_test();
-void string_test();
-void expr_test();
-void macro_test();
-void recursive_macro_test();
-void scope_test();
-void forward_test();
-void funcptr_test();
-void loop_test();
-void switch_test();
-void goto_test();
-void enum_test();
-void typedef_test();
-void struct_test();
-void array_test();
-void expr_ptr_test();
-void bool_test();
-void optimize_out();
-void expr2_test();
-void constant_expr_test();
-void expr_cmp_test();
-void char_short_test();
-void init_test(void);
-void compound_literal_test(void);
-int kr_test();
-void struct_assign_test(void);
-void cast_test(void);
-void bitfield_test(void);
-void c99_bool_test(void);
-void float_test(void);
-void longlong_test(void);
-void manyarg_test(void);
-void stdarg_test(void);
-void whitespace_test(void);
-void relocation_test(void);
-void old_style_function(void);
-void alloca_test(void);
-void c99_vla_test(int size1, int size2);
-void sizeof_test(void);
-void typeof_test(void);
-void local_label_test(void);
-void statement_expr_test(void);
-void asm_test(void);
-void builtin_test(void);
-void weak_test(void);
-void global_data_test(void);
-void cmp_comparison_test(void);
-void math_cmp_test(void);
-void callsave_test(void);
-void builtin_frame_address_test(void);
-void attrib_test(void);
-
int fib(int n);
void num(int n);
void forward_ref(void);
@@ -133,8 +86,6 @@ int isid(int c);
void funny_line_continuation (int, ..\
. );
-char via_volatile (char);
-
#define A 2
#define N 1234 + A
#define pf printf
@@ -178,7 +129,7 @@ static int onetwothree = 123;
#ifdef __TINYC__
/* We try to handle this syntax. Make at least sure it doesn't segfault. */
-char invalid_function_def()[] {}
+char invalid_function_def()[] {return 0;}
#endif
#define __INT64_C(c) c ## LL
@@ -194,74 +145,8 @@ int qq(int x)
#define wq_spin_lock spin_lock
#define TEST2() wq_spin_lock(a)
-#define UINT_MAX ((unsigned) -1)
-
-void intdiv_test(void)
-{
- printf("18/21=%u\n", 18/21);
- printf("18%%21=%u\n", 18%21);
- printf("41/21=%u\n", 41/21);
- printf("41%%21=%u\n", 41%21);
- printf("42/21=%u\n", 42/21);
- printf("42%%21=%u\n", 42%21);
- printf("43/21=%u\n", 43/21);
- printf("43%%21=%u\n", 43%21);
- printf("126/21=%u\n", 126/21);
- printf("126%%21=%u\n", 126%21);
- printf("131/21=%u\n", 131/21);
- printf("131%%21=%u\n", 131%21);
- printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2);
- printf("(UINT_MAX/2+3)%%2=%u\n", (UINT_MAX/2+3)%2);
-
- printf("18/-21=%u\n", 18/-21);
- printf("18%%-21=%u\n", 18%-21);
- printf("41/-21=%u\n", 41/-21);
- printf("41%%-21=%u\n", 41%-21);
- printf("42/-21=%u\n", 42/-21);
- printf("42%%-21=%u\n", 42%-21);
- printf("43/-21=%u\n", 43/-21);
- printf("43%%-21=%u\n", 43%-21);
- printf("126/-21=%u\n", 126/-21);
- printf("126%%-21=%u\n", 126%-21);
- printf("131/-21=%u\n", 131/-21);
- printf("131%%-21=%u\n", 131%-21);
- printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2);
- printf("(UINT_MAX/2+3)%%-2=%u\n", (UINT_MAX/2+3)%-2);
-
- printf("-18/21=%u\n", -18/21);
- printf("-18%%21=%u\n", -18%21);
- printf("-41/21=%u\n", -41/21);
- printf("-41%%21=%u\n", -41%21);
- printf("-42/21=%u\n", -42/21);
- printf("-42%%21=%u\n", -42%21);
- printf("-43/21=%u\n", -43/21);
- printf("-43%%21=%u\n", -43%21);
- printf("-126/21=%u\n", -126/21);
- printf("-126%%21=%u\n", -126%21);
- printf("-131/21=%u\n", -131/21);
- printf("-131%%21=%u\n", -131%21);
- printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2);
- printf("-(UINT_MAX/2+3)%%2=%u\n", (0-(UINT_MAX/2+3))%2);
-
- printf("-18/-21=%u\n", -18/-21);
- printf("-18%%-21=%u\n", -18%-21);
- printf("-41/-21=%u\n", -41/-21);
- printf("-41%%-21=%u\n", -41%-21);
- printf("-42/-21=%u\n", -42/-21);
- printf("-42%%-21=%u\n", -42%-21);
- printf("-43/-21=%u\n", -43/-21);
- printf("-43%%-21=%u\n", -43%-21);
- printf("-126/-21=%u\n", -126/-21);
- printf("-126%%-21=%u\n", -126%-21);
- printf("-131/-21=%u\n", -131/-21);
- printf("-131%%-21=%u\n", -131%-21);
- printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2);
- printf("-(UINT_MAX/2+3)%%-2=%u\n", (0-(UINT_MAX/2+3))%-2);
-}
-
void macro_test(void)
{
- printf("macro:\n");
pf("N=%d\n", N);
printf("aaa=%d\n", AAA);
@@ -336,22 +221,6 @@ void macro_test(void)
MACRO_NOARGS();
-#ifdef __LINE__
- printf("__LINE__ defined\n");
-#endif
-
- printf("__LINE__=%d __FILE__=%s\n",
- __LINE__, __FILE__);
-#if 0
-#line 200
- printf("__LINE__=%d __FILE__=%s\n",
- __LINE__, __FILE__);
-#line 203 "test"
- printf("__LINE__=%d __FILE__=%s\n",
- __LINE__, __FILE__);
-#line 227 "tcctest.c"
-#endif
-
/* not strictly preprocessor, but we test it there */
#ifdef C99_MACROS
printf("__func__ = %s\n", __func__);
@@ -408,15 +277,25 @@ comment
comment. */
TEST2 /* the comment */ ();
- printf("%s\n", get_basefile_from_header());
- printf("%s\n", __BASE_FILE__);
- printf("%s\n", get_file_from_header());
- printf("%s\n", __FILE__);
+ printf("basefromheader %s\n", get_basefile_from_header());
+ printf("base %s\n", __BASE_FILE__);
+ {
+ /* Some compilers (clang) prepend './' to __FILE__ from included
+ files. */
+ const char *fn = get_file_from_header();
+ if (fn[0] == '.' && fn[1] == '/')
+ fn += 2;
+ printf("filefromheader %s\n", fn);
+ }
+ printf("file %s\n", __FILE__);
/* Check that funnily named include was in fact included */
have_included_42test_h = 1;
have_included_42test_h_second = 1;
have_included_42test_h_third = 1;
+
+ /* Check that we don't complain about stray \ here */
+ printf("print a backslash: %s\n", stringify(\\));
}
@@ -461,6 +340,56 @@ int ret(a)
return 0;
}
+#if !defined(__TINYC__) && (__GNUC__ >= 8)
+/* Old GCCs don't regard "foo"[1] as constant, even in GNU dialect. */
+#define CONSTANTINDEXEDSTRLIT
+#endif
+char str_ag1[] = "b";
+char str_ag2[] = { "b" };
+/*char str_bg1[] = ("cccc"); GCC accepts this with pedantic warning, TCC not */
+#ifdef CONSTANTINDEXEDSTRLIT
+char str_ag3[] = { "ab"[1], 0 };
+char str_x[2] = { "xy" "z"[2], 0 };
+#endif
+char *str_ar[] = { "one", "two" };
+struct str_SS {unsigned char a[3], b; };
+struct str_SS str_sinit15 = { "r" };
+struct str_SS str_sinit16[] = { { "q" }, 2 };
+
+static void string_test2()
+{
+ char *p = "hello";
+ char a3[2] = { "p" };
+ char a4[2] = { "ab" "c"[2], 0 };
+ char *pa1 = "def" + 1;
+ char *pa2 = { "xyz" + 1 };
+ int i = 0;
+ struct str_SS ss = { { [0 ... 1] = 'a' }, 0 };
+#ifndef CONSTANTINDEXEDSTRLIT
+ char str_ag3[] = { "ab"[1], 0 };
+ char str_x[2] = { "xy" "z"[2], 0 };
+#endif
+ puts("string_test2");
+ puts(str_ag1);
+ puts(str_ag2);
+ /*puts(str_bg1);*/
+ puts(str_ag3);
+ puts(str_x);
+ puts(str_sinit15.a);
+ puts(str_sinit16[0].a);
+ puts(a3);
+ puts(a4);
+ puts(p);
+ puts("world");
+ printf("%s\n", "bla");
+ puts(str_ar[0]);
+ puts(str_ar[1]);
+ puts(ss.a);
+ puts(i >= 0 ? "one" : "two");
+ puts(pa1);
+ puts(pa2);
+}
+
void ps(const char *s)
{
int c;
@@ -505,6 +434,52 @@ void string_test()
num(b);
b = b * 2;
}
+ string_test2();
+}
+
+
+void if1t(int n, int a, int b, int c)
+{
+ if (a && b) printf("if1t: %d 1 %d %d\n", n, a, b);
+ if (a && !b) printf("if1t: %d 2 %d %d\n", n, a, b);
+ if (!a && b) printf("if1t: %d 3 %d %d\n", n, a, b);
+ if (!a && !b) printf("if1t: %d 4 %d %d\n", n, a, b);
+ if (a || b) printf("if1t: %d 5 %d %d\n", n, a, b);
+ if (a || !b) printf("if1t: %d 6 %d %d\n", n, a, b);
+ if (!a || b) printf("if1t: %d 7 %d %d\n", n, a, b);
+ if (!a || !b) printf("if1t: %d 8 %d %d\n", n, a, b);
+ if (a && b || c) printf("if1t: %d 9 %d %d %d\n", n, a, b, c);
+ if (a || b && c) printf("if1t: %d 10 %d %d %d\n", n, a, b, c);
+ if (a > b - 1 && c) printf("if1t: %d 11 %d %d %d\n", n, a, b, c);
+ if (a > b - 1 || c) printf("if1t: %d 12 %d %d %d\n", n, a, b, c);
+ if (a > 0 && 1) printf("if1t: %d 13 %d %d %d\n", n, a, b, c);
+ if (a > 0 || 0) printf("if1t: %d 14 %d %d %d\n", n, a, b, c);
+}
+
+void if2t(void)
+{
+ if (0 && 1 || printf("if2t:ok\n") || 1)
+ printf("if2t:ok2\n");
+ printf("if2t:ok3\n");
+}
+
+void if3t(void)
+{
+ volatile long long i = 1;
+ if (i <= 18446744073709551615ULL)
+ ;
+ else
+ printf ("if3t:wrong 1\n");
+}
+
+void if_test(void)
+{
+ if1t(1, 0, 0, 0);
+ if1t(2, 0, 3, 0);
+ if1t(3, 2, 0, 0);
+ if1t(4, 2, 3, 0);
+ if2t();
+ if3t();
}
void loop_test()
@@ -568,9 +543,10 @@ void goto_test()
int i;
static void *label_table[3] = { &&label1, &&label2, &&label3 };
- printf("goto:\n");
+ printf("\ngoto:\n");
i = 0;
/* This needs to parse as label, not as start of decl. */
+ typedef_and_label x;
typedef_and_label:
s_loop:
if (i >= 10)
@@ -635,8 +611,7 @@ void enum_test()
/* The following should give no warning */
unsigned *p = &b1;
struct S_enum s = {E7};
- printf("enum: %d\n", s.e);
- printf("enum:\n%d %d %d %d %d %d\n",
+ printf("%d %d %d %d %d %d %d\n", s.e,
E0, E1, E2, E3, E4, E5);
b1 = 1;
printf("b1=%d\n", b1);
@@ -665,7 +640,6 @@ void typedef_test()
a = &b;
*a = 1234;
- printf("typedef:\n");
printf("a=%d\n", *a);
mytype2 = 2;
printf("mytype2=%d\n", mytype2);
@@ -673,7 +647,6 @@ void typedef_test()
void forward_test()
{
- printf("forward:\n");
forward_ref();
forward_ref();
}
@@ -711,66 +684,6 @@ struct empty_mem {
int x;
};
-int main(int argc, char **argv)
-{
- string_test();
- expr_test();
- macro_test();
- recursive_macro_test();
- scope_test();
- forward_test();
- funcptr_test();
- loop_test();
- switch_test();
- goto_test();
- enum_test();
- typedef_test();
- struct_test();
- array_test();
- expr_ptr_test();
- bool_test();
- optimize_out();
- expr2_test();
- constant_expr_test();
- expr_cmp_test();
- char_short_test();
- init_test();
- compound_literal_test();
- kr_test();
- struct_assign_test();
- cast_test();
- bitfield_test();
- c99_bool_test();
- float_test();
- longlong_test();
- manyarg_test();
- stdarg_test();
- whitespace_test();
- relocation_test();
- old_style_function();
- alloca_test();
- c99_vla_test(5, 2);
- sizeof_test();
- typeof_test();
- statement_expr_test();
- local_label_test();
- asm_test();
- builtin_test();
-#ifndef _WIN32
- weak_test();
-#endif
- global_data_test();
- cmp_comparison_test();
- math_cmp_test();
- callsave_test();
- builtin_frame_address_test();
- intdiv_test();
- if (via_volatile (42) != 42)
- printf ("via_volatile broken\n");
- attrib_test();
- return 0;
-}
-
int tab[3];
int tab2[3][2];
@@ -783,7 +696,6 @@ void f1(g)
void scope_test()
{
- printf("scope:\n");
g = 2;
f1(1);
printf("g2=%d\n", g);
@@ -800,11 +712,34 @@ void scope_test()
printf("g5=%d\n", g);
}
+int st2_i;
+int *st2_p = &st2_i;
+void scope2_test()
+{
+ char a[50];
+ st2_i = 42;
+ for (int st2_i = 1; st2_i < 10; st2_i++) {
+ extern int st2_i;
+ st2_i++;
+ printf("exloc: %d\n", st2_i);
+ }
+ printf("exloc: %d\n", *st2_p);
+}
+
+/* C has tentative definition, and they may be repeated. */
+extern int st_global1;
+int st_global1=42;
+extern int st_global1;
+int st_global1;
+extern int st_global2;
+int st_global2;
+extern int st_global2;
+int st_global2;
+
void array_test()
{
int i, j, a[4];
- printf("array:\n");
printf("sizeof(a) = %d\n", sizeof(a));
printf("sizeof(\"a\") = %d\n", sizeof("a"));
#ifdef C99_MACROS
@@ -909,7 +844,6 @@ void expr2_test()
{
int a, b;
- printf("expr2:\n");
vstack_ptr = vstack;
vpush(1432432, 2);
vstack_ptr[-2] &= ~0xffffff80;
@@ -917,14 +851,16 @@ void expr2_test()
printf("res= %d %d\n", a, b);
}
+int const_len_ar[sizeof(1/0)]; /* div-by-zero, but in unevaluated context */
+
void constant_expr_test()
{
int a;
- printf("constant_expr:\n");
a = 3;
printf("%d\n", a * 16);
printf("%d\n", a * 1);
printf("%d\n", a + 0);
+ printf("%d\n", sizeof(const_len_ar));
}
int tab4[10];
@@ -934,7 +870,6 @@ void expr_ptr_test()
int *p, *q;
int i = -1;
- printf("expr_ptr:\n");
p = tab4;
q = tab4 + 10;
printf("diff=%d\n", q - p);
@@ -990,7 +925,6 @@ void expr_ptr_test()
void expr_cmp_test()
{
int a, b;
- printf("constant_expr:\n");
a = -1;
b = 1;
printf("%d\n", a == a);
@@ -1110,7 +1044,6 @@ void struct_test()
union union2 u;
struct Large ls;
- printf("struct:\n");
printf("sizes: %d %d %d %d\n",
sizeof(struct struct1),
sizeof(struct struct2),
@@ -1134,7 +1067,7 @@ void struct_test()
s->f3 = 1;
printf("st2: %d %d %d\n",
s->f1, s->f2, s->f3);
- printf("str_addr=%x\n", (int)st1.str - (int)&st1.f1);
+ printf("str_addr=%x\n", (int)(uintptr_t)st1.str - (int)(uintptr_t)&st1.f1);
/* align / size tests */
printf("aligntest1 sizeof=%d alignof=%d\n",
@@ -1174,17 +1107,22 @@ void struct_test()
printf("Large: offsetof(compound_head)=%d\n", (int)((char*)&ls.compound_head - (char*)&ls));
}
+/* simulate char/short return value with undefined upper bits */
+static int __csf(int x) { return x; }
+static void *_csf = __csf;
+#define csf(t,n) ((t(*)(int))_csf)(n)
+
/* XXX: depend on endianness */
void char_short_test()
{
int var1, var2;
-
- printf("char_short:\n");
+ signed char var3;
+ long long var4;
var1 = 0x01020304;
var2 = 0xfffefdfc;
printf("s8=%d %d\n",
- *(char *)&var1, *(char *)&var2);
+ *(signed char *)&var1, *(signed char *)&var2);
printf("u8=%d %d\n",
*(unsigned char *)&var1, *(unsigned char *)&var2);
printf("s16=%d %d\n",
@@ -1195,12 +1133,44 @@ void char_short_test()
*(int *)&var1, *(int *)&var2);
printf("u32=%d %d\n",
*(unsigned int *)&var1, *(unsigned int *)&var2);
- *(char *)&var1 = 0x08;
+ *(signed char *)&var1 = 0x08;
printf("var1=%x\n", var1);
*(short *)&var1 = 0x0809;
printf("var1=%x\n", var1);
*(int *)&var1 = 0x08090a0b;
printf("var1=%x\n", var1);
+
+ var1 = 0x778899aa;
+ var4 = 0x11223344aa998877ULL;
+ var1 = var3 = var1 + 1;
+ var4 = var3 = var4 + 1;
+ printf("promote char/short assign %d "LONG_LONG_FORMAT"\n", var1, var4);
+ var1 = 0x778899aa;
+ var4 = 0x11223344aa998877ULL;
+ printf("promote char/short assign VA %d %d\n", var3 = var1 + 1, var3 = var4 + 1);
+ printf("promote char/short cast VA %d %d\n", (signed char)(var1 + 1), (signed char)(var4 + 1));
+#if !defined(__arm__)
+ /* We can't really express GCC behaviour of return type promotion in
+ the presence of undefined behaviour (like __csf is). */
+ var1 = csf(unsigned char,0x89898989);
+ var4 = csf(signed char,0xabababab);
+ printf("promote char/short funcret %d "LONG_LONG_FORMAT"\n", var1, var4);
+ printf("promote char/short fumcret VA %d %d %d %d\n",
+ csf(unsigned short,0xcdcdcdcd),
+ csf(short,0xefefefef),
+ csf(_Bool,0x33221100),
+ csf(_Bool,0x33221101));
+#endif
+ var3 = -10;
+ var1 = (signed char)(unsigned char)(var3 + 1);
+ var4 = (signed char)(unsigned char)(var3 + 1);
+ printf("promote multicast (char)(unsigned char) %d "LONG_LONG_FORMAT"\n", var1, var4);
+ var4 = 0x11223344aa998877ULL;
+ var4 = (unsigned)(int)(var4 + 1);
+ printf("promote multicast (unsigned)(int) "LONG_LONG_FORMAT"\n", var4);
+ var4 = 0x11223344bbaa9988ULL;
+ var4 = (unsigned)(signed char)(var4 + 1);
+ printf("promote multicast (unsigned)(char) "LONG_LONG_FORMAT"\n", var4);
}
/******************/
@@ -1307,12 +1277,16 @@ void bool_test()
extern int undefined_function(void);
extern int defined_function(void);
+#ifdef __clang__
+int undefined_function(void) {}
+#endif
+
static inline void refer_to_undefined(void)
{
undefined_function();
}
-void optimize_out(void)
+void optimize_out_test(void)
{
int i = 0 ? undefined_function() : defined_function();
printf ("oo:%d\n", i);
@@ -1374,6 +1348,12 @@ void optimize_out(void)
printf("ool6:%d\n", defined_function());
goto breakhere;
}
+ j = 1;
+ while (j) {
+ j--;
+ continue;
+ printf("ool7:%d\n", undefined_function());
+ }
/* Test that constants in logical && are optimized: */
i = 0 && undefined_function();
@@ -1433,6 +1413,9 @@ int defined_function(void)
static int tab_reinit[];
static int tab_reinit[10];
+static int tentative_ar[];
+static int tentative_ar[] = {1,2,3};
+
//int cinit1; /* a global variable can be defined several times without error ! */
int cinit1;
int cinit1;
@@ -1444,8 +1427,6 @@ void compound_literal_test(void)
int *p, i;
char *q, *q3;
- printf("compound_test:\n");
-
p = (int []){1, 2, 3};
for(i=0;i<3;i++)
printf(" %d", p[i]);
@@ -1497,7 +1478,6 @@ int kr_func2(a, b)
kr_test()
{
- printf("kr_test:\n");
printf("func1=%d\n", kr_func1(3, 4));
printf("func2=%d\n", kr_func2(3, 4));
return 0;
@@ -1553,8 +1533,6 @@ void struct_assign_test(void)
ps = &s;
ps->i = 4;
#if 0
- printf("struct_assign_test:\n");
-
s.lsta1.f1 = 1;
s.lsta1.f2 = 2;
printf("%d %d\n", s.lsta1.f1, s.lsta1.f2);
@@ -1597,9 +1575,9 @@ void cast_test()
unsigned b,d;
short s;
char *p = NULL;
+ unsigned long ul = 0x80000000UL;
p -= 0x700000000042;
- printf("cast_test:\n");
a = 0xfffff;
cast1(a, a, a, a);
a = 0xffffe;
@@ -1640,15 +1618,20 @@ void cast_test()
printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a'));
printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a'));
+#if CC_NAME != CC_clang /* clang doesn't support non-portable conversions */
/* from pointer to integer types */
printf("%d %d %ld %ld %lld %lld\n",
(int)p, (unsigned int)p,
(long)p, (unsigned long)p,
(long long)p, (unsigned long long)p);
+#endif
/* from integers to pointers */
printf("%p %p %p %p\n",
(void *)a, (void *)b, (void *)c, (void *)d);
+
+ /* int to int with sign set */
+ printf("0x%lx\n", (unsigned long)(int)ul);
}
/* initializers tests */
@@ -1752,6 +1735,8 @@ arrtype2 sinit22 = {5,6,7};
int sinit23[2] = { "astring" ? sizeof("astring") : -1,
&sinit23 ? 42 : -1 };
+int sinit24 = 2 || 1 / 0; /* exception in constant but unevaluated context */
+
extern int external_inited = 42;
void init_test(void)
@@ -1772,8 +1757,6 @@ void init_test(void)
/* Addresses on non-weak symbols are non-zero, but not the access itself */
int linit18[2] = {&zero ? 1 : -1, zero ? -1 : 1 };
- printf("init_test:\n");
-
printf("sinit1=%d\n", sinit1);
printf("sinit2=%d\n", sinit2);
printf("sinit3=%d %d %d %d\n",
@@ -1866,6 +1849,7 @@ void init_test(void)
printf("arrtype6: %d\n", sizeof(arrtype2));
printf("sinit23= %d %d\n", sinit23[0], sinit23[1]);
+ printf("sinit24=%d\n", sinit24);
printf("linit18= %d %d\n", linit18[0], linit18[1]);
}
@@ -1991,9 +1975,8 @@ void c99_bool_test(void)
{
#ifdef BOOL_ISOC99
int a;
- _Bool b;
+ _Bool b, b2;
- printf("bool_test:\n");
printf("sizeof(_Bool) = %d\n", sizeof(_Bool));
a = 3;
printf("cast: %d %d %d\n", (_Bool)10, (_Bool)0, (_Bool)a);
@@ -2001,6 +1984,9 @@ void c99_bool_test(void)
printf("b = %d\n", b);
b++;
printf("b = %d\n", b);
+ b2 = 0;
+ printf("sizeof(x ? _Bool : _Bool) = %d (should be sizeof int)\n",
+ sizeof((volatile)a ? b : b2));
#endif
}
@@ -2018,7 +2004,6 @@ void bitfield_test(void)
int f4 : 7;
unsigned int f5 : 7;
} st1;
- printf("bitfield_test:");
printf("sizeof(st1) = %d\n", sizeof(st1));
st1.f1 = 3;
@@ -2230,12 +2215,15 @@ double ftab1[3] = { 1.2, 3.4, -5.6 };
void float_test(void)
{
#if !defined(__arm__) || defined(__ARM_PCS_VFP)
- float fa, fb;
- double da, db;
+ volatile float fa, fb;
+ volatile double da, db;
int a;
unsigned int b;
+ static double nan2 = 0.0/0.0;
+ static double inf1 = 1.0/0.0;
+ static double inf2 = 1e5000;
+ volatile LONG_DOUBLE la;
- printf("float_test:\n");
printf("sizeof(float) = %d\n", sizeof(float));
printf("sizeof(double) = %d\n", sizeof(double));
printf("sizeof(long double) = %d\n", sizeof(LONG_DOUBLE));
@@ -2255,6 +2243,31 @@ void float_test(void)
b = 4000000000;
db = b;
printf("db = %f\n", db);
+ printf("nan != nan = %d, inf1 = %f, inf2 = %f\n", nan2 != nan2, inf1, inf2);
+ da = 0x0.88p-1022; /* a subnormal */
+ la = da;
+ printf ("da subnormal = %a\n", da);
+ printf ("da subnormal = %.40g\n", da);
+ printf ("la subnormal = %La\n", la);
+ printf ("la subnormal = %.40Lg\n", la);
+ da /= 2;
+ la = da;
+ printf ("da/2 subnormal = %a\n", da);
+ printf ("da/2 subnormal = %.40g\n", da);
+ printf ("la/2 subnormal = %La\n", la);
+ printf ("la/2 subnormal = %.40Lg\n", la);
+ fa = 0x0.88p-126f; /* a subnormal */
+ la = fa;
+ printf ("fa subnormal = %a\n", fa);
+ printf ("fa subnormal = %.40g\n", fa);
+ printf ("la subnormal = %La\n", la);
+ printf ("la subnormal = %.40Lg\n", la);
+ fa /= 2;
+ la = fa;
+ printf ("fa/2 subnormal = %a\n", fa);
+ printf ("fa/2 subnormal = %.40g\n", fa);
+ printf ("la/2 subnormal = %La\n", la);
+ printf ("la/2 subnormal = %.40Lg\n", la);
#endif
}
@@ -2266,6 +2279,12 @@ int fib(int n)
return fib(n-1) + fib(n-2);
}
+#if __GNUC__ == 3
+# define aligned_function 0
+#else
+void __attribute__((aligned(16))) aligned_function(int i) {}
+#endif
+
void funcptr_test()
{
void (*func)(int);
@@ -2276,7 +2295,6 @@ void funcptr_test()
} st1;
long diff;
- printf("funcptr:\n");
func = &num;
(*func)(12345);
func = num;
@@ -2296,6 +2314,10 @@ void funcptr_test()
func(42);
(func + diff)(42);
(num + a)(43);
+
+ /* Check that we can align functions */
+ func = aligned_function;
+ printf("aligned_function (should be zero): %d\n", ((int)(uintptr_t)func) & 15);
}
void lloptest(long long a, long long b)
@@ -2420,12 +2442,16 @@ long long llfunc2(long long x, long long y, int z)
return x * y * z;
}
+void check_opl_save_regs(char *a, long long b, int c)
+{
+ *a = b < 0 && !c;
+}
+
void longlong_test(void)
{
long long a, b, c;
int ia;
unsigned int ua;
- printf("longlong_test:\n");
printf("sizeof(long long) = %d\n", sizeof(long long));
ia = -1;
ua = -2;
@@ -2487,12 +2513,24 @@ void longlong_test(void)
a = 0x123;
long long *p = &a;
llshift(*p, 5);
+
+ /* shortening followed by widening */
+ unsigned long long u = 0x8000000000000001ULL;
+ u = (unsigned)(u + 1);
+ printf("long long u=" ULONG_LONG_FORMAT "\n", u);
+ u = 0x11223344aa998877ULL;
+ u = (unsigned)(int)(u + 1);
+ printf("long long u=" ULONG_LONG_FORMAT "\n", u);
+
+ /* was a problem with missing save_regs in gen_opl on 32-bit platforms */
+ char cc = 78;
+ check_opl_save_regs(&cc, -1, 0);
+ printf("check_opl_save_regs: %d\n", cc);
}
void manyarg_test(void)
{
LONG_DOUBLE ld = 1234567891234LL;
- printf("manyarg_test:\n");
printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f\n",
1, 2, 3, 4, 5, 6, 7, 8,
0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0);
@@ -2524,6 +2562,18 @@ void manyarg_test(void)
42.0, 43.0, ld);
}
+void*
+va_arg_with_struct_ptr(va_list ap) {
+ /*
+ * This was a BUG identified with FFTW-3.3.8 on arm64.
+ * The test case only checks it compiles on all supported
+ * architectures. This function is not currently called.
+ */
+ struct X { int _x; };
+ struct X *x = va_arg(ap, struct X *);
+ return x;
+}
+
void vprintf1(const char *fmt, ...)
{
va_list ap, aq;
@@ -2601,6 +2651,19 @@ void stdarg_for_libc(const char *fmt, ...)
va_end(args);
}
+void stdarg_syntax(int n, ...)
+{
+ int i;
+ va_list ap;
+ if (1)
+ va_start(ap, n);
+ else
+ ;
+ i = va_arg(ap, int);
+ printf("stdarg_void_expr: %d\n", i);
+ (va_end(ap));
+}
+
void stdarg_test(void)
{
LONG_DOUBLE ld = 1234567891234LL;
@@ -2648,38 +2711,7 @@ void stdarg_test(void)
bob.profile = 42;
stdarg_for_struct(bob, bob, bob, bob.profile);
stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456);
-}
-
-void whitespace_test(void)
-{
- char *str;
-
- #if 1
- pri\
-ntf("whitspace:\n");
-#endif
- pf("N=%d\n", 2);
-
-#ifdef CORRECT_CR_HANDLING
- pri\
-ntf("aaa=%d\n", 3);
-#endif
-
- pri\
-\
-ntf("min=%d\n", 4);
-
-#ifdef ACCEPT_CR_IN_STRINGS
- printf("len1=%d\n", strlen("
-"));
-#ifdef CORRECT_CR_HANDLING
- str = "
-";
- printf("len1=%d str[0]=%d\n", strlen(str), str[0]);
-#endif
- printf("len1=%d\n", strlen(" a
-"));
-#endif /* ACCEPT_CR_IN_STRINGS */
+ stdarg_syntax(1, 17);
}
int reltab[3] = { 1, 2, 3 };
@@ -2738,7 +2770,7 @@ int cmpfn();
printf("cmpfn=%lx\n", (long)cmpfn);
}
-void old_style_function(void)
+void old_style_function_test(void)
{
old_style_f((void *)1, 2, 3.0);
decl_func1(NULL);
@@ -2765,7 +2797,7 @@ void *bounds_checking_is_enabled()
typedef int constant_negative_array_size_as_compile_time_assertion_idiom[(1 ? 2 : 0) - 1];
-void c99_vla_test(int size1, int size2)
+void c99_vla_test_1(int size1, int size2)
{
#if defined __i386__ || defined __x86_64__
int size = size1 * size2;
@@ -2816,9 +2848,11 @@ void c99_vla_test(int size1, int size2)
#endif
}
-#ifndef __TINYC__
-typedef __SIZE_TYPE__ uintptr_t;
-#endif
+void c99_vla_test(void)
+{
+ c99_vla_test_1(5, 2);
+}
+
void sizeof_test(void)
{
@@ -2962,6 +2996,22 @@ void statement_expr_test(void)
/* Test that we can give out addresses of local labels. */
consume_ulong(({ __label__ __here; __here: (unsigned long)&&__here; }));
+
+ /* Test interaction between local and global label stacks and the
+ need to defer popping symbol from them when within statement
+ expressions. Note how the labels are both named LBL. */
+ i = 0;
+ ({
+ {
+ __label__ LBL;
+ LBL: if (i++ == 0) goto LBL;
+ }
+ /* jump to a classical label out of an expr-stmt that had previously
+ overshadowed that classical label */
+ goto LBL;
+ });
+ LBL:
+ printf("stmtexpr: %d should be 2\n", i);
}
void local_label_test(void)
@@ -3087,6 +3137,8 @@ static __inline__ void sigdelset1(unsigned int *set, int _sig)
asm("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc", "flags");
}
+#ifndef __APPLE__
+/* clang's inline asm is uncapable of 'xchgb %b0,%h0' */
static __inline__ __const__ unsigned int swab32(unsigned int x)
{
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
@@ -3096,6 +3148,7 @@ static __inline__ __const__ unsigned int swab32(unsigned int x)
: "0" (x));
return x;
}
+#endif
static __inline__ unsigned long long mul64(unsigned int a, unsigned int b)
{
@@ -3172,6 +3225,7 @@ void base_func(void)
printf ("asmc: base\n");
}
+#ifndef __APPLE__
extern void override_func1 (void);
extern void override_func2 (void);
@@ -3189,6 +3243,21 @@ void override_func2 (void)
extern int bug_table[] __attribute__((section("__bug_table")));
char * get_asm_string (void)
{
+ /* On i386 when -fPIC is enabled this would cause a compile error with GCC,
+ the problem being the "i" constraint used with a symbolic operand
+ resolving to a local label. That check is overly zealous as the code
+ within the asm makes sure to use it only in PIC-possible contexts,
+ but all GCC versions behave like so. We arrange for PIC to be disabled
+ for compiling tcctest.c in the Makefile.
+
+ Additionally the usage of 'c' in "%c0" in the template is actually wrong,
+ as that would expect an operand that is a condition code. The operand
+ as is (a local label) is accepted by GCC in non-PIC mode, and on x86-64.
+ What the linux kernel really wanted is 'p' to disable the addition of '$'
+ to the printed operand (as in "$.LC0" where the template only wants the
+ bare operand ".LC0"). But the code below is what the linux kernel
+ happens to use and as such is the one we want to test. */
+#ifndef __clang__
extern int some_symbol;
asm volatile (".globl some_symbol\n"
"jmp .+6\n"
@@ -3204,6 +3273,9 @@ char * get_asm_string (void)
".popsection\n" : : "i" ("A string"));
char * str = ((char*)bug_table) + bug_table[1];
return str;
+#else
+ return (char *) "A string";
+#endif
}
/* This checks another constructs with local labels. */
@@ -3225,6 +3297,7 @@ void asm_local_label_diff (void)
{
printf ("asm_local_label_diff: %d %d\n", alld_stuff[0], alld_stuff[1]);
}
+#endif
/* This checks that static local variables are available from assembler. */
void asm_local_statics (void)
@@ -3255,7 +3328,7 @@ void clobber_r12(void)
}
#endif
-void test_high_clobbers(void)
+void test_high_clobbers_really(void)
{
#if defined __x86_64__ && !defined _WIN64
register long val asm("r12");
@@ -3271,6 +3344,20 @@ void test_high_clobbers(void)
#endif
}
+void test_high_clobbers(void)
+{
+#if defined __x86_64__ && !defined _WIN64
+ long x1, x2;
+ asm volatile("mov %%r12,%0" :: "m" (x1)); /* save r12 */
+ test_high_clobbers_really();
+ asm volatile("mov %%r12,%0" :: "m" (x2)); /* new r12 */
+ asm volatile("mov %0,%%r12" :: "m" (x1)); /* restore r12 */
+ /* should be 0 but tcc doesn't save r12 automatically, which has
+ bad effects when gcc helds TCCState *s in r12 in tcc.c:main */
+ //printf("r12-clobber-diff: %lx\n", x2 - x1);
+#endif
+}
+
static long cpu_number;
void trace_console(long len, long len2)
{
@@ -3359,8 +3446,10 @@ void test_asm_call(void)
tested here). */
/* two pushes so stack remains aligned */
asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;"
-#if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__))
+#if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) && !defined(__APPLE__)
"call getenv@plt;"
+#elif defined(__APPLE__)
+ "call _getenv;"
#else
"call getenv;"
#endif
@@ -3378,6 +3467,7 @@ void test_asm_call(void)
void asm_dot_test(void)
{
+#ifndef __APPLE__
int x;
for (x = 1;; ++x) {
int r = x;
@@ -3385,13 +3475,31 @@ void asm_dot_test(void)
case 1:
asm(".text; lea S"RX",%eax; lea ."RX",%ecx; sub %ecx,%eax; S=.; jmp p0");
case 2:
+#ifndef __clang__
+ /* clangs internal assembler is broken */
asm(".text; jmp .+6; .int 123; mov .-4"RX",%eax; jmp p0");
+#else
+ asm(".text; mov $123, %eax; jmp p0");
+#endif
case 3:
- asm(".data; Y=.; .int 999; X=Y; .int 456; X=.-4");
+#if !defined(_WIN32) && !defined(__clang__)
+ asm(".pushsection \".data\"; Y=.; .int 999; X=Y; .int 456; X=.-4; .popsection");
+#else
+ asm(".data; Y=.; .int 999; X=Y; .int 456; X=.-4; .text");
+#endif
asm(".text; mov X"RX",%eax; jmp p0");
case 4:
- asm(".data; X=.; .int 789; Y=.; .int 999");
+#ifdef __clang__
+ /* Bah! Clang! Doesn't want to redefine 'X' */
+ asm(".text; mov $789,%eax; jmp p0");
+#else
+#ifndef _WIN32
+ asm(".data; X=.; .int 789; Y=.; .int 999; .previous");
+#else
+ asm(".data; X=.; .int 789; Y=.; .int 999; .text");
+#endif
asm(".text; mov X"RX",%eax; X=Y; jmp p0");
+#endif
case 0:
asm(".text; p0=.; mov %%eax,%0;" : "=m"(r)); break;
}
@@ -3399,6 +3507,7 @@ void asm_dot_test(void)
break;
printf("asm_dot_test %d: %d\n", x, r);
}
+#endif
}
void asm_test(void)
@@ -3417,8 +3526,6 @@ void asm_test(void)
#endif
register int regvar asm("%esi");
- printf("inline asm:\n");
-
// parse 0x1E-1 as 3 tokens in asm mode
asm volatile ("mov $0x1E-1,%eax");
@@ -3452,8 +3559,11 @@ void asm_test(void)
__asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");
printf("set=0x%x\n", set);
val = 0x01020304;
+#ifndef __APPLE__
printf("swab32(0x%08x) = 0x%0x\n", val, swab32(val));
+#endif
#ifndef _WIN32
+#ifndef __APPLE__
override_func1();
override_func2();
/* The base_func ref from the following inline asm should find
@@ -3462,13 +3572,17 @@ void asm_test(void)
override_func3();
printf("asmstr: %s\n", get_asm_string());
asm_local_label_diff();
+#endif
asm_local_statics();
#endif
+#ifndef __clang__
+ /* clang can't deal with the type change */
/* Check that we can also load structs of appropriate layout
into registers. */
asm volatile("" : "=r" (asmret) : "0"(s2));
if (asmret != s2.addr)
printf("asmstr: failed\n");
+#endif
#ifdef BOOL_ISOC99
/* Check that the typesize correctly sets the register size to
8 bit. */
@@ -3530,11 +3644,24 @@ void builtin_test(void)
/* space is needed because tcc preprocessor introduces a space between each token */
COMPAT_TYPE(char * *, void *);
#endif
- printf("res = %d\n", __builtin_constant_p(1));
- printf("res = %d\n", __builtin_constant_p(1 + 2));
- printf("res = %d\n", __builtin_constant_p(&constant_p_var));
- printf("res = %d\n", __builtin_constant_p(constant_p_var));
- printf("res = %d\n", __builtin_constant_p(100000 / constant_p_var));
+ printf("res1 = %d\n", __builtin_constant_p(1));
+ printf("res2 = %d\n", __builtin_constant_p(1 + 2));
+ printf("res3 = %d\n", __builtin_constant_p(&constant_p_var));
+ printf("res4 = %d\n", __builtin_constant_p(constant_p_var));
+ printf("res5 = %d\n", __builtin_constant_p(100000 / constant_p_var));
+#ifdef __clang__
+ /* clang doesn't regard this as constant expression */
+ printf("res6 = 1\n");
+#else
+ printf("res6 = %d\n", __builtin_constant_p(i && 0));
+#endif
+ printf("res7 = %d\n", __builtin_constant_p(i && 1));
+#ifdef __clang__
+ /* clang doesn't regard this as constant expression */
+ printf("res8 = 1\n");
+#else
+ printf("res8 = %d\n", __builtin_constant_p(i && 0 ? i : 34));
+#endif
s = 1;
ll = 2;
i = __builtin_choose_expr (1 != 0, ll, s);
@@ -3549,7 +3676,9 @@ void builtin_test(void)
//printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
}
-#ifndef _WIN32
+#ifdef _WIN32
+void weak_test(void) {}
+#else
extern int __attribute__((weak)) weak_f1(void);
extern int __attribute__((weak)) weak_f2(void);
extern int weak_f3(void);
@@ -3568,14 +3697,18 @@ extern int weak_asm_v1 asm("weak_asm_v1x") __attribute
extern int __attribute((weak)) weak_asm_v2 asm("weak_asm_v2x") ;
extern int __attribute((weak)) weak_asm_v3(void) asm("weak_asm_v3x") __attribute((weak));
+#ifndef __clang__
static const size_t dummy = 0;
extern __typeof(dummy) weak_dummy1 __attribute__((weak, alias("dummy")));
extern __typeof(dummy) __attribute__((weak, alias("dummy"))) weak_dummy2;
extern __attribute__((weak, alias("dummy"))) __typeof(dummy) weak_dummy3;
+#endif
int some_lib_func(void);
int dummy_impl_of_slf(void) { return 444; }
+#ifndef __clang__
int some_lib_func(void) __attribute__((weak, alias("dummy_impl_of_slf")));
+#endif
int weak_toolate() __attribute__((weak));
int weak_toolate() { return 0; }
@@ -3599,7 +3732,11 @@ void __attribute__((weak)) weak_test(void)
printf("weak_asm_v1=%d\n",&weak_asm_v1 != NULL);
printf("weak_asm_v2=%d\n",&weak_asm_v2 != NULL);
printf("weak_asm_v3=%d\n",&weak_asm_v3 != NULL);
+#ifdef __clang__
+ printf("some_lib_func=444\n");
+#else
printf("some_lib_func=%d\n", &some_lib_func ? some_lib_func() : 0);
+#endif
}
int __attribute__((weak)) weak_f2() { return 222; }
@@ -3695,6 +3832,7 @@ int fcompare (double a, double b, int code)
case 4: return a > b;
case 5: return a <= b;
}
+ return 0;
}
void math_cmp_test(void)
@@ -3703,6 +3841,7 @@ void math_cmp_test(void)
double one = 1.0;
double two = 2.0;
int comp = 0;
+ int v;
#define bug(a,b,op,iop,part) printf("Test broken: %s %s %s %s %d\n", #a, #b, #op, #iop, part)
/* This asserts that "a op b" is _not_ true, but "a iop b" is true.
@@ -3724,7 +3863,8 @@ void math_cmp_test(void)
if ((a iop b) || comp) \
; \
else \
- bug (a,b,op,iop,5);
+ bug (a,b,op,iop,5); \
+ if (v = !(a op b), !v) bug(a,b,op,iop,7);
/* Equality tests. */
FCMP(nan, nan, ==, !=, 0);
@@ -3793,8 +3933,10 @@ void builtin_frame_address_test(void)
char *fp0 = __builtin_frame_address(0);
printf("str: %s\n", str);
+#ifndef __riscv
bfa1(str-fp0);
#endif
+#endif
}
char via_volatile (char i)
@@ -3804,6 +3946,14 @@ char via_volatile (char i)
return vi;
}
+void volatile_test(void)
+{
+ if (via_volatile (42) != 42)
+ printf (" broken\n");
+ else
+ printf (" ok\n");
+}
+
struct __attribute__((__packed__)) Spacked {
char a;
short b;
@@ -3869,3 +4019,137 @@ int force_get_order(unsigned long s)
{
return __get_order(s);
}
+
+#define pv(m) printf(sizeof (s->m + 0) == 8 ? "%016llx\n" : "%02x\n", s->m)
+
+/* Test failed when using bounds checking */
+void bounds_check1_test (void)
+{
+ struct s {
+ int x;
+ long long y;
+ } _s, *s = &_s;
+ s->x = 10;
+ s->y = 20;
+ pv(x);
+ pv(y);
+}
+
+/* gcc 2.95.3 does not handle correctly CR in strings or after strays */
+#define CORRECT_CR_HANDLING
+
+/* deprecated and no longer supported in gcc 3.3 */
+#ifdef __TINYC__
+# define ACCEPT_CR_IN_STRINGS
+#endif
+
+/* keep this as the last test because GCC messes up line-numbers
+ with the ^L^K^M characters below */
+void whitespace_test(void)
+{
+ char *str;
+
+ #if 1
+ pri\
+ntf("whitspace:\n");
+#endif
+ pf("N=%d\n", 2);
+
+#ifdef CORRECT_CR_HANDLING
+ pri\
+ntf("aaa=%d\n", 3);
+#endif
+
+ pri\
+\
+ntf("min=%d\n", 4);
+
+#ifdef ACCEPT_CR_IN_STRINGS
+ printf("len1=%d\n", strlen("
+"));
+#ifdef CORRECT_CR_HANDLING
+ str = "
+";
+ printf("len1=%d str[0]=%d\n", strlen(str), str[0]);
+#endif
+ printf("len1=%d\n", strlen(" a
+"));
+#else
+ printf("len1=1\nlen1=1 str[0]=10\nlen1=3\n");
+#endif /* ACCEPT_CR_IN_STRINGS */
+
+#ifdef __LINE__
+ printf("__LINE__ defined\n");
+#endif
+
+#if 0
+ /* wrong with GCC */
+ printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__);
+#line 1111
+ printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__);
+#line 2222 "test"
+ printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__);
+#endif
+}
+
+#define RUN(test) puts("---- " #test " ----"), test(), puts("")
+
+int main(int argc, char **argv)
+{
+ RUN(whitespace_test);
+ RUN(macro_test);
+ RUN(recursive_macro_test);
+ RUN(string_test);
+ RUN(expr_test);
+ RUN(scope_test);
+ RUN(scope2_test);
+ RUN(forward_test);
+ RUN(funcptr_test);
+ RUN(if_test);
+ RUN(loop_test);
+ RUN(switch_test);
+ RUN(goto_test);
+ RUN(enum_test);
+ RUN(typedef_test);
+ RUN(struct_test);
+ RUN(array_test);
+ RUN(expr_ptr_test);
+ RUN(bool_test);
+ RUN(optimize_out_test);
+ RUN(expr2_test);
+ RUN(constant_expr_test);
+ RUN(expr_cmp_test);
+ RUN(char_short_test);
+ RUN(init_test);
+ RUN(compound_literal_test);
+ RUN(kr_test);
+ RUN(struct_assign_test);
+ RUN(cast_test);
+ RUN(bitfield_test);
+ RUN(c99_bool_test);
+ RUN(float_test);
+ RUN(longlong_test);
+ RUN(manyarg_test);
+ RUN(stdarg_test);
+ RUN(relocation_test);
+ RUN(old_style_function_test);
+ RUN(alloca_test);
+ RUN(c99_vla_test);
+ RUN(sizeof_test);
+ RUN(typeof_test);
+ RUN(statement_expr_test);
+ RUN(local_label_test);
+ RUN(asm_test);
+ RUN(builtin_test);
+ RUN(weak_test);
+ RUN(global_data_test);
+ RUN(cmp_comparison_test);
+ RUN(math_cmp_test);
+ RUN(callsave_test);
+ RUN(builtin_frame_address_test);
+ RUN(volatile_test);
+ RUN(attrib_test);
+ RUN(bounds_check1_test);
+
+ return 0;
+}
diff --git a/tests/tests2/03_struct.c b/tests/tests2/03_struct.c
index c5d48c5..fd73133 100644
--- a/tests/tests2/03_struct.c
+++ b/tests/tests2/03_struct.c
@@ -1,6 +1,13 @@
-#include <stdio.h>
+extern int printf(const char*, ...);
-struct fred
+struct fred;
+
+void fred$(struct fred* this)
+{
+ printf("~fred()\n");
+}
+
+struct __attribute__((__cleanup__(fred$))) fred
{
int boris;
int natasha;
@@ -8,7 +15,7 @@ struct fred
int main()
{
- struct fred bloggs;
+ struct fred __attribute__((__cleanup__(fred$))) bloggs;
bloggs.boris = 12;
bloggs.natasha = 34;
diff --git a/tests/tests2/03_struct.expect b/tests/tests2/03_struct.expect
index ecbf589..be8df37 100644
--- a/tests/tests2/03_struct.expect
+++ b/tests/tests2/03_struct.expect
@@ -1,6 +1,8 @@
+03_struct.c:14: warning: attribute '__cleanup__' ignored on type
12
34
12
34
56
78
+~fred()
diff --git a/tests/tests2/07_function.c b/tests/tests2/07_function.c
index 0477ce1..006e0a7 100644
--- a/tests/tests2/07_function.c
+++ b/tests/tests2/07_function.c
@@ -15,6 +15,11 @@ void qfunc()
printf("qfunc()\n");
}
+void zfunc()
+{
+ ((void (*)(void))0) ();
+}
+
int main()
{
printf("%d\n", myfunc(3));
diff --git a/tests/tests2/100_c99array-decls.c b/tests/tests2/100_c99array-decls.c
new file mode 100644
index 0000000..46950aa
--- /dev/null
+++ b/tests/tests2/100_c99array-decls.c
@@ -0,0 +1,34 @@
+void foo(int [5]);
+void fooc(int x[const 5]);
+void foos(int x[static 5]);
+void foov(int x[volatile 5]);
+void foor(int x[restrict 5]);
+void fooc(int [const 5]);
+void foos(int [static 5]);
+void foov(int [volatile 5]);
+void foor(int [restrict 5]);
+void fooc(int (* const x));
+void foos(int *x);
+void foov(int * volatile x);
+void foor(int * restrict x);
+void fooc(int x[volatile 5])
+{
+ x[3] = 42;
+#ifdef INVALID
+ x = 0;
+#endif
+}
+void foovm(int x[const *]);
+void foovm(int * const x);
+#ifdef INVALID
+void wrongc(int x[3][const 4]);
+void wrongvm(int x[static *]);
+void foovm(int x[const *])
+{
+ x[2] = 1;
+}
+#endif
+int main()
+{
+ return 0;
+}
diff --git a/tests/tests2/100_c99array-decls.expect b/tests/tests2/100_c99array-decls.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/tests2/100_c99array-decls.expect
diff --git a/tests/tests2/101_cleanup.c b/tests/tests2/101_cleanup.c
new file mode 100644
index 0000000..de5dca2
--- /dev/null
+++ b/tests/tests2/101_cleanup.c
@@ -0,0 +1,227 @@
+extern int printf(const char*, ...);
+static int glob_i = 0;
+
+void incr_glob_i(int *i)
+{
+ glob_i += *i;
+}
+
+#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;
+ }
+ }
+ return;
+}
+
+void check_oh_i(char *oh_i)
+{
+ printf("c: %c\n", *oh_i);
+}
+
+void goto_hell(double *f)
+{
+ printf("oo: %f\n", *f);
+}
+
+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);
+}
+
+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");
+}
+
+int main()
+{
+ int i __attribute__ ((__cleanup__(check))) = 0, not_i;
+ int chk = 0;
+ (void)not_i;
+
+ {
+ __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();
+ return i;
+}
+
+void check2(char **hum)
+{
+ printf("str: %s\n", *hum);
+}
diff --git a/tests/tests2/101_cleanup.expect b/tests/tests2/101_cleanup.expect
new file mode 100644
index 0000000..84960cd
--- /dev/null
+++ b/tests/tests2/101_cleanup.expect
@@ -0,0 +1,59 @@
+c: a
+c: o
+glob_i: 65536
+oo: 2.600000
+c: f
+str: I don't think this should be print(but gcc got it wrong too)
+because what if free was call inside cleanup function I don't think this should be print(but gcc got it wrong too)
+should be print before
+str: that
+str: this should appear only once
+str: -that2
+str: -that
+str: test2
+str: one
+---- 1
+str: two
+str: three
+-- loop 0 --
+100
+100
+100
+100
+100
+100
+100
+100
+100
+100
+10
+-- loop 1 --
+200
+200
+200
+200
+200
+200
+200
+200
+200
+200
+10
+-- loop 2 --
+300
+0
+-- loop 3 --
+400
+500
+400
+after break
+1000
+---- 0
+---- 1
+str: plop
+str: tata !
+str: 3
+str: 2
+str: 1
+str: last goto out
+str: wololo
diff --git a/tests/tests2/102_alignas.c b/tests/tests2/102_alignas.c
new file mode 100644
index 0000000..62d3ed2
--- /dev/null
+++ b/tests/tests2/102_alignas.c
@@ -0,0 +1,29 @@
+_Alignas(16) int i1;
+int _Alignas(16) i2;
+void _Alignas(16) *p2;
+_Alignas(16) i3;
+int _Alignas(double) i4;
+int _Alignas(int) i5;
+#if 0
+/* The following are currently wrongly accepted by TCC but really shouldn't. */
+int _Alignas(int _Alignas(16)) i6; //wrong, 'int _Alignas(16)' is no type-name
+typedef int _Alignas(16) int16aligned_t; //wrong, _Alignas invalid on typedef
+int16aligned_t i7;
+#endif
+/* i8 should get an alignment of 16, because unlike _Alignas the
+ corresponding attribute _does_ apply to type-name, though not in
+ some clang versions. */
+int _Alignas(int __attribute__((aligned(16)))) i8;
+extern int printf(const char*, ...);
+#ifdef _MSC_VER
+#define alignof(x) (int)__alignof(x)
+#else
+#define alignof(x) (int)__alignof__(x)
+#endif
+int main()
+{
+ printf("%d %d %d %d\n",
+ alignof(i1) == 16, alignof(i4) == alignof(double),
+ alignof(i5) == alignof(int) , alignof(i8) == 16);
+ return 0;
+}
diff --git a/tests/tests2/102_alignas.expect b/tests/tests2/102_alignas.expect
new file mode 100644
index 0000000..ac6474a
--- /dev/null
+++ b/tests/tests2/102_alignas.expect
@@ -0,0 +1 @@
+1 1 1 1
diff --git a/tests/tests2/103_implicit_memmove.c b/tests/tests2/103_implicit_memmove.c
new file mode 100644
index 0000000..1592fb2
--- /dev/null
+++ b/tests/tests2/103_implicit_memmove.c
@@ -0,0 +1,20 @@
+/* Test that the memmove TCC is emitting for the struct copy
+ and hence implicitely declares can be declared properly also
+ later. */
+struct S { int a,b,c,d, e[1024];};
+int foo (struct S *a, struct S *b)
+{
+ *a = *b;
+ return 0;
+}
+
+void *memmove(void*,const void*,__SIZE_TYPE__);
+void foo2 (struct S *a, struct S *b)
+{
+ memmove(a, b, sizeof *a);
+}
+
+int main()
+{
+ return 0;
+}
diff --git a/tests/tests2/103_implicit_memmove.expect b/tests/tests2/103_implicit_memmove.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/tests2/103_implicit_memmove.expect
diff --git a/tests/tests2/104+_inline.c b/tests/tests2/104+_inline.c
new file mode 100644
index 0000000..1209fd4
--- /dev/null
+++ b/tests/tests2/104+_inline.c
@@ -0,0 +1,54 @@
+
+#define GOT(f) \
+ __attribute__((weak)) void f(void); \
+ printf("%d %s\n", !!f, #f);
+
+int printf(const char*, ...);
+
+void check_exports()
+{
+ // 0
+ GOT(inline_inline_2decl_only)
+ GOT(inline_inline_undeclared)
+ GOT(inline_inline_predeclared)
+ GOT(inline_inline_postdeclared)
+ GOT(inline_inline_prepostdeclared)
+ GOT(inline_inline_undeclared2)
+ GOT(inline_inline_predeclared2)
+ GOT(inline_inline_postdeclared2)
+ GOT(inline_inline_prepostdeclared2)
+
+ // 1
+ GOT(extern_extern_postdeclared)
+ GOT(extern_extern_postdeclared2)
+ GOT(extern_extern_predeclared)
+ GOT(extern_extern_predeclared2)
+ GOT(extern_extern_prepostdeclared)
+ GOT(extern_extern_prepostdeclared2)
+ GOT(extern_extern_undeclared)
+ GOT(extern_extern_undeclared2)
+ GOT(extern_postdeclared)
+ GOT(extern_postdeclared2)
+ GOT(extern_predeclared)
+ GOT(extern_predeclared2)
+ GOT(extern_prepostdeclared)
+ GOT(extern_undeclared)
+ GOT(extern_undeclared2)
+ GOT(inst2_extern_inline_postdeclared)
+ GOT(inst2_extern_inline_predeclared)
+ GOT(inst3_extern_inline_predeclared)
+ GOT(inst_extern_inline_postdeclared)
+ GOT(inst_extern_inline_predeclared)
+ GOT(main)
+ GOT(noinst_extern_inline_func)
+ GOT(noinst_extern_inline_postdeclared)
+ GOT(noinst_extern_inline_postdeclared2)
+ GOT(noinst_extern_inline_undeclared)
+
+ // 0
+ GOT(noinst_static_inline_postdeclared)
+ GOT(noinst2_static_inline_postdeclared)
+ GOT(noinst_static_inline_predeclared)
+ GOT(noinst2_static_inline_predeclared)
+ GOT(static_func)
+}
diff --git a/tests/tests2/104_inline.c b/tests/tests2/104_inline.c
new file mode 100644
index 0000000..766f94a
--- /dev/null
+++ b/tests/tests2/104_inline.c
@@ -0,0 +1,132 @@
+inline void inline_inline_2decl_only(void);
+inline void inline_inline_2decl_only(void);
+
+inline void inline_inline_undeclared(void){}
+
+inline void inline_inline_predeclared(void);
+inline void inline_inline_predeclared(void){}
+
+inline void inline_inline_postdeclared(void){}
+inline void inline_inline_postdeclared(void);
+
+inline void inline_inline_prepostdeclared(void);
+inline void inline_inline_prepostdeclared(void){}
+inline void inline_inline_prepostdeclared(void);
+
+inline void inline_inline_undeclared2(void){}
+
+inline void inline_inline_predeclared2(void);
+inline void inline_inline_predeclared2(void);
+inline void inline_inline_predeclared2(void){}
+
+inline void inline_inline_postdeclared2(void){}
+inline void inline_inline_postdeclared2(void);
+inline void inline_inline_postdeclared2(void);
+
+inline void inline_inline_prepostdeclared2(void);
+inline void inline_inline_prepostdeclared2(void);
+inline void inline_inline_prepostdeclared2(void){}
+inline void inline_inline_prepostdeclared2(void);
+inline void inline_inline_prepostdeclared2(void);
+
+extern void extern_extern_undeclared(void){}
+
+extern void extern_extern_predeclared(void);
+extern void extern_extern_predeclared(void){}
+
+extern void extern_extern_postdeclared(void){}
+extern void extern_extern_postdeclared(void);
+
+extern void extern_extern_prepostdeclared(void);
+extern void extern_extern_prepostdeclared(void){}
+extern void extern_extern_prepostdeclared(void);
+
+extern void extern_extern_undeclared2(void){}
+
+extern void extern_extern_predeclared2(void);
+extern void extern_extern_predeclared2(void);
+extern void extern_extern_predeclared2(void){}
+
+extern void extern_extern_postdeclared2(void){}
+extern void extern_extern_postdeclared2(void);
+extern void extern_extern_postdeclared2(void);
+
+extern void extern_extern_prepostdeclared2(void);
+extern void extern_extern_prepostdeclared2(void);
+extern void extern_extern_prepostdeclared2(void){}
+extern void extern_extern_prepostdeclared2(void);
+extern void extern_extern_prepostdeclared2(void);
+
+void extern_undeclared(void){}
+
+void extern_predeclared(void);
+void extern_predeclared(void){}
+
+void extern_postdeclared(void){}
+void extern_postdeclared(void);
+
+void extern_prepostdeclared(void);
+void extern_prepostdeclared(void){}
+void extern_prepostdeclared(void);
+
+void extern_undeclared2(void){}
+
+void extern_predeclared2(void);
+void extern_predeclared2(void);
+void extern_predeclared2(void){}
+
+void extern_postdeclared2(void){}
+void extern_postdeclared2(void);
+void extern_postdeclared2(void);
+
+
+extern inline void noinst_extern_inline_undeclared(void){}
+
+extern inline void noinst_extern_inline_postdeclared(void){}
+inline void noinst_extern_inline_postdeclared(void);
+
+extern inline void noinst_extern_inline_postdeclared2(void){}
+inline void noinst_extern_inline_postdeclared2(void);
+inline void noinst_extern_inline_postdeclared2(void);
+
+extern inline void inst_extern_inline_postdeclared(void){}
+extern inline void inst_extern_inline_postdeclared(void);
+inline void inst2_extern_inline_postdeclared(void){}
+void inst2_extern_inline_postdeclared(void);
+
+void inst_extern_inline_predeclared(void);
+extern inline void inst_extern_inline_predeclared(void){}
+void inst2_extern_inline_predeclared(void);
+inline void inst2_extern_inline_predeclared(void){}
+extern inline void inst3_extern_inline_predeclared(void);
+inline void inst3_extern_inline_predeclared(void){}
+
+static inline void noinst_static_inline_postdeclared(void){}
+static inline void noinst_static_inline_postdeclared(void);
+static inline void noinst2_static_inline_postdeclared(void){}
+static void noinst2_static_inline_postdeclared(void);
+
+static void noinst_static_inline_predeclared(void);
+static inline void noinst_static_inline_predeclared(void){}
+static void noinst2_static_inline_predeclared(void);
+static inline void noinst2_static_inline_predeclared(void){}
+
+static void static_func(void);
+void static_func(void) { }
+
+inline void noinst_extern_inline_func(void);
+void noinst_extern_inline_func(void) { }
+
+int main()
+{
+ inline_inline_undeclared(); inline_inline_predeclared(); inline_inline_postdeclared();
+ inline_inline_undeclared2(); inline_inline_predeclared2(); inline_inline_postdeclared2();
+ noinst_static_inline_predeclared();
+ noinst2_static_inline_predeclared();
+ noinst_static_inline_predeclared();
+ noinst2_static_inline_predeclared();
+
+ void check_exports();
+ check_exports();
+ return 0;
+}
diff --git a/tests/tests2/104_inline.expect b/tests/tests2/104_inline.expect
new file mode 100644
index 0000000..bdb0994
--- /dev/null
+++ b/tests/tests2/104_inline.expect
@@ -0,0 +1,39 @@
+0 inline_inline_2decl_only
+0 inline_inline_undeclared
+0 inline_inline_predeclared
+0 inline_inline_postdeclared
+0 inline_inline_prepostdeclared
+0 inline_inline_undeclared2
+0 inline_inline_predeclared2
+0 inline_inline_postdeclared2
+0 inline_inline_prepostdeclared2
+1 extern_extern_postdeclared
+1 extern_extern_postdeclared2
+1 extern_extern_predeclared
+1 extern_extern_predeclared2
+1 extern_extern_prepostdeclared
+1 extern_extern_prepostdeclared2
+1 extern_extern_undeclared
+1 extern_extern_undeclared2
+1 extern_postdeclared
+1 extern_postdeclared2
+1 extern_predeclared
+1 extern_predeclared2
+1 extern_prepostdeclared
+1 extern_undeclared
+1 extern_undeclared2
+1 inst2_extern_inline_postdeclared
+1 inst2_extern_inline_predeclared
+1 inst3_extern_inline_predeclared
+1 inst_extern_inline_postdeclared
+1 inst_extern_inline_predeclared
+1 main
+1 noinst_extern_inline_func
+1 noinst_extern_inline_postdeclared
+1 noinst_extern_inline_postdeclared2
+1 noinst_extern_inline_undeclared
+0 noinst_static_inline_postdeclared
+0 noinst2_static_inline_postdeclared
+0 noinst_static_inline_predeclared
+0 noinst2_static_inline_predeclared
+0 static_func
diff --git a/tests/tests2/105_local_extern.c b/tests/tests2/105_local_extern.c
new file mode 100644
index 0000000..a248bb4
--- /dev/null
+++ b/tests/tests2/105_local_extern.c
@@ -0,0 +1,12 @@
+extern int printf(const char *, ...);
+void f(void);
+void bar(void) { void f(void); f(); }
+void foo(void) { extern void f(void); f(); }
+void f(void) { printf("f\n"); }
+
+int main()
+{
+ bar();
+ foo();
+ return 0;
+}
diff --git a/tests/tests2/105_local_extern.expect b/tests/tests2/105_local_extern.expect
new file mode 100644
index 0000000..445ae74
--- /dev/null
+++ b/tests/tests2/105_local_extern.expect
@@ -0,0 +1,2 @@
+f
+f
diff --git a/tests/tests2/106_pthread.c b/tests/tests2/106_pthread.c
new file mode 100644
index 0000000..09308ed
--- /dev/null
+++ b/tests/tests2/106_pthread.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <pthread.h>
+#include <errno.h>
+
+int
+main(void)
+{
+ int ret;
+ pthread_condattr_t attr;
+ pthread_cond_t condition;
+
+ pthread_condattr_init (&attr);
+ pthread_condattr_setpshared (&attr, PTHREAD_PROCESS_SHARED);
+ printf ("%s\n", pthread_cond_init (&condition, &attr) ? "fail":"ok");
+ pthread_condattr_destroy (&attr);
+ return 0;
+}
diff --git a/tests/tests2/106_pthread.expect b/tests/tests2/106_pthread.expect
new file mode 100644
index 0000000..9766475
--- /dev/null
+++ b/tests/tests2/106_pthread.expect
@@ -0,0 +1 @@
+ok
diff --git a/tests/tests2/107_stack_safe.c b/tests/tests2/107_stack_safe.c
new file mode 100644
index 0000000..479c84d
--- /dev/null
+++ b/tests/tests2/107_stack_safe.c
@@ -0,0 +1,13 @@
+extern int printf(const char *, ...);
+
+static void func_ull_ull(unsigned long long l1,unsigned long long l2){
+}
+
+int main()
+{
+ int a,b,c,d;
+ a=1;b=2;c=3;d=4;
+ func_ull_ull((unsigned long long)a/1.0,(unsigned long long)b/1.0);
+ printf("%d %d %d %d",a,b,c,d);
+ return 0;
+}
diff --git a/tests/tests2/107_stack_safe.expect b/tests/tests2/107_stack_safe.expect
new file mode 100644
index 0000000..e9e9cd7
--- /dev/null
+++ b/tests/tests2/107_stack_safe.expect
@@ -0,0 +1 @@
+1 2 3 4 \ No newline at end of file
diff --git a/tests/tests2/108_constructor.c b/tests/tests2/108_constructor.c
new file mode 100644
index 0000000..145d0da
--- /dev/null
+++ b/tests/tests2/108_constructor.c
@@ -0,0 +1,20 @@
+extern int write (int fd, void *buf, int len);
+
+static void __attribute__ ((constructor))
+testc (void)
+{
+ write (1, "constructor\n", 12);
+}
+
+static void __attribute__ ((destructor))
+testd (void)
+{
+ write (1, "destructor\n", 11);
+}
+
+int
+main (void)
+{
+ write (1, "main\n", 5);
+ return 0;
+}
diff --git a/tests/tests2/108_constructor.expect b/tests/tests2/108_constructor.expect
new file mode 100644
index 0000000..167ca51
--- /dev/null
+++ b/tests/tests2/108_constructor.expect
@@ -0,0 +1,3 @@
+constructor
+main
+destructor
diff --git a/tests/tests2/109_float_struct_calling.c b/tests/tests2/109_float_struct_calling.c
new file mode 100644
index 0000000..90fc045
--- /dev/null
+++ b/tests/tests2/109_float_struct_calling.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+/* This test used to fail on x86_64 on linux with sse registers */
+
+struct Point {
+ float x;
+ float y;
+};
+
+struct Rect {
+ struct Point top_left;
+ struct Point size;
+};
+
+float foo(struct Point p, struct Rect r) {
+ return r.size.x;
+}
+
+int main(int argc, char **argv) {
+ struct Point p = {1, 2};
+ struct Rect r = {{3, 4}, {5, 6}};
+ printf("%f\n", foo(p, r));
+ return 0;
+}
diff --git a/tests/tests2/109_float_struct_calling.expect b/tests/tests2/109_float_struct_calling.expect
new file mode 100644
index 0000000..eaa6787
--- /dev/null
+++ b/tests/tests2/109_float_struct_calling.expect
@@ -0,0 +1 @@
+5.000000
diff --git a/tests/tests2/110_average.c b/tests/tests2/110_average.c
new file mode 100644
index 0000000..273b511
--- /dev/null
+++ b/tests/tests2/110_average.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+typedef struct
+{
+ double average;
+ int count;
+}
+stats_type;
+
+static void
+testc (stats_type *s, long long data)
+{
+ s->average = (s->average * s->count + data) / (s->count + 1);
+ s->count++;
+}
+
+int main (void)
+{
+ stats_type s;
+
+ s.average = 0;
+ s.count = 0;
+ testc (&s, 10);
+ testc (&s, 20);
+ printf ("%g %d\n", s.average, s.count);
+ return 0;
+}
diff --git a/tests/tests2/110_average.expect b/tests/tests2/110_average.expect
new file mode 100644
index 0000000..4955335
--- /dev/null
+++ b/tests/tests2/110_average.expect
@@ -0,0 +1 @@
+15 2
diff --git a/tests/tests2/111_conversion.c b/tests/tests2/111_conversion.c
new file mode 100644
index 0000000..c0815e1
--- /dev/null
+++ b/tests/tests2/111_conversion.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+union u {
+ unsigned long ul;
+ long double ld;
+};
+
+void
+conv (union u *p)
+{
+ p->ul = (unsigned int) p->ld;
+}
+
+int main (void)
+{
+ union u v;
+
+ v.ld = 42;
+ conv (&v);
+ printf ("%lu\n", v.ul);
+ return 0;
+}
diff --git a/tests/tests2/111_conversion.expect b/tests/tests2/111_conversion.expect
new file mode 100644
index 0000000..d81cc07
--- /dev/null
+++ b/tests/tests2/111_conversion.expect
@@ -0,0 +1 @@
+42
diff --git a/tests/tests2/112_backtrace.c b/tests/tests2/112_backtrace.c
new file mode 100644
index 0000000..8489bd3
--- /dev/null
+++ b/tests/tests2/112_backtrace.c
@@ -0,0 +1,165 @@
+#include <stdio.h>
+
+/* ------------------------------------------------------- */
+#if defined test_backtrace_1
+
+void f3()
+{
+ printf("* f3()\n"), fflush(stdout);
+ *(void**)0 = 0;
+}
+void f2()
+{
+ printf("* f2()\n"), fflush(stdout);
+ f3();
+}
+void f1()
+{
+ printf("* f1()\n"), fflush(stdout);
+ f2();
+}
+int main(int argc, char **argv)
+{
+ printf("* main\n"), fflush(stdout);
+ f1();
+ printf("* exit main\n"), fflush(stdout);
+ return 0;
+}
+
+/* ------------------------------------------------------- */
+#elif defined test_bcheck_1
+
+struct s { int a,b,c,d,e; };
+struct s s[3];
+struct s *ps = s;
+void f1()
+{
+ printf("* f1()\n"), fflush(stdout);
+ ps[3] = ps[2];
+}
+int main(int argc, char **argv)
+{
+ printf("* main\n"), fflush(stdout);
+ f1();
+ printf("* exit main\n"), fflush(stdout);
+ return 0;
+}
+
+/* ------------------------------------------------------- */
+#elif defined test_tcc_backtrace_2
+
+/* test custom backtrace and 'exit()' redirection */
+int tcc_backtrace(const char *fmt, ...);
+void exit(int);
+
+void f2()
+{
+ printf("* f2()\n");
+ printf("* exit f2\n"), fflush(stdout);
+ exit(34);
+}
+void f1()
+{
+ printf("* f1()\n"), fflush(stdout);
+ tcc_backtrace("Hello from %s!", "f1");
+ f2();
+}
+int main(int argc, char **argv)
+{
+ printf("* main\n"), fflush(stdout);
+ f1();
+ printf("* exit main\n"), fflush(stdout);
+ return 0;
+}
+
+/* ------------------------------------------------------- */
+#elif defined test_tcc_backtrace_3
+
+/* this test should be run despite of the exit(34) above */
+int main(int argc, char **argv)
+{
+ printf("* main\n"), fflush(stdout);
+ return 1;
+}
+
+/* ------------------------------------------------------- */
+#else
+#include <stdlib.h>
+#include <string.h>
+char *strdup();
+int main()
+{
+ char pad1[10];
+ char a[10];
+ char pad2[10];
+ char b[10];
+ char pad3[10];
+ memset (pad1, 0, sizeof(pad1));
+ memset (pad2, 0, sizeof(pad2));
+ memset (pad3, 0, sizeof(pad3));
+
+ memset (a, 'a', 10);
+ a[3] = 0;
+ a[9] = 0;
+ memset (b, 'b', 10);
+
+#if defined test_bcheck_100
+ memcpy(&a[1],&b[0],10);
+#elif defined test_bcheck_101
+ memcpy(&a[0],&b[1],10);
+#elif defined test_bcheck_102
+ memcpy(&a[0],&a[3],4);
+#elif defined test_bcheck_103
+ memcpy(&a[3],&a[0],4);
+#elif defined test_bcheck_104
+ memcmp(&b[1],&b[0],10);
+#elif defined test_bcheck_105
+ memcmp(&b[0],&b[1],10);
+#elif defined test_bcheck_106
+ memmove(&b[1],&b[0],10);
+#elif defined test_bcheck_107
+ memmove(&b[0],&b[1],10);
+#elif defined test_bcheck_108
+ memset(&b[1],'b',10);
+#elif defined test_bcheck_109
+ strlen(&b[0]);
+#elif defined test_bcheck_110
+ strcpy(&a[7], &a[0]);
+#elif defined test_bcheck_111
+ strcpy(&a[0], &b[7]);
+#elif defined test_bcheck_112
+ strcpy(&a[0], &a[1]);
+#elif defined test_bcheck_113
+ strcpy(&a[2], &a[0]);
+#elif defined test_bcheck_114
+ strncpy(&a[7], &a[0], 10);
+#elif defined test_bcheck_115
+ strncpy(&a[0], &b[7], 10);
+#elif defined test_bcheck_116
+ strncpy(&a[0], &a[1], 10);
+#elif defined test_bcheck_117
+ strncpy(&a[2], &a[0], 10);
+#elif defined test_bcheck_118
+ strcmp(&b[2], &b[0]);
+#elif defined test_bcheck_119
+ strcmp(&b[0], &b[2]);
+#elif defined test_bcheck_120
+ strncmp(&b[5], &b[0], 10);
+#elif defined test_bcheck_121
+ strncmp(&b[0], &b[5], 10);
+#elif defined test_bcheck_122
+ strcat(&a[7], &a[0]);
+#elif defined test_bcheck_123
+ strcat(&a[0], &b[3]);
+#elif defined test_bcheck_124
+ strcat(&a[0], &a[4]);
+#elif defined test_bcheck_125
+ strcat(&a[3], &a[0]);
+#elif defined test_bcheck_126
+ strchr(&b[0], 'a');
+#elif defined test_bcheck_127
+ free(strdup(&b[0]));
+#endif
+}
+/* ------------------------------------------------------- */
+#endif
diff --git a/tests/tests2/112_backtrace.expect b/tests/tests2/112_backtrace.expect
new file mode 100644
index 0000000..68986c6
--- /dev/null
+++ b/tests/tests2/112_backtrace.expect
@@ -0,0 +1,142 @@
+[test_backtrace_1]
+* main
+* f1()
+* f2()
+* f3()
+112_backtrace.c:9: at f3: RUNTIME ERROR: invalid memory access
+112_backtrace.c:14: by f2
+112_backtrace.c:19: by f1
+112_backtrace.c:24: by main
+[returns 255]
+
+[test_bcheck_1]
+* main
+* f1()
+112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x? in memmove dest
+112_backtrace.c:43: by main
+[returns 255]
+
+[test_tcc_backtrace_2]
+* main
+* f1()
+112_backtrace.c:64: at f1: Hello from f1!
+112_backtrace.c:70: by main
+* f2()
+* exit f2
+[returns 34]
+
+[test_tcc_backtrace_3]
+* main
+[returns 1]
+
+[test_bcheck_100]
+112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0x? in memcpy dest
+[returns 255]
+
+[test_bcheck_101]
+112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0x? in memcpy src
+[returns 255]
+
+[test_bcheck_102]
+112_backtrace.c:111: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in memcpy
+[returns 255]
+
+[test_bcheck_103]
+112_backtrace.c:113: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in memcpy
+[returns 255]
+
+[test_bcheck_104]
+112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s1
+[returns 255]
+
+[test_bcheck_105]
+112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s2
+[returns 255]
+
+[test_bcheck_106]
+112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0x? in memmove dest
+[returns 255]
+
+[test_bcheck_107]
+112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0x? in memmove src
+[returns 255]
+
+[test_bcheck_108]
+112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0x? in memset
+[returns 255]
+
+[test_bcheck_109]
+112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0x? in strlen
+[returns 255]
+
+[test_bcheck_110]
+112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x? in strcpy dest
+[returns 255]
+
+[test_bcheck_111]
+112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x? in strcpy src
+[returns 255]
+
+[test_bcheck_112]
+112_backtrace.c:131: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strcpy
+[returns 255]
+
+[test_bcheck_113]
+112_backtrace.c:133: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strcpy
+[returns 255]
+
+[test_bcheck_114]
+112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x? in strncpy dest
+[returns 255]
+
+[test_bcheck_115]
+112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x? in strncpy src
+[returns 255]
+
+[test_bcheck_116]
+112_backtrace.c:139: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strncpy
+[returns 255]
+
+[test_bcheck_117]
+112_backtrace.c:141: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strncpy
+[returns 255]
+
+[test_bcheck_118]
+112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s1
+[returns 255]
+
+[test_bcheck_119]
+112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s2
+[returns 255]
+
+[test_bcheck_120]
+112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s1
+[returns 255]
+
+[test_bcheck_121]
+112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s2
+[returns 255]
+
+[test_bcheck_122]
+112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest
+[returns 255]
+
+[test_bcheck_123]
+112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest
+[returns 255]
+
+[test_bcheck_124]
+112_backtrace.c:155: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strcat
+[returns 255]
+
+[test_bcheck_125]
+112_backtrace.c:157: at main: BCHECK: overlapping regions ........(0x?), ........(0x?) in strcat
+[returns 255]
+
+[test_bcheck_126]
+112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0x? in strchr
+[returns 255]
+
+[test_bcheck_127]
+112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0x? in strdup
+[returns 255]
diff --git a/tests/tests2/113_btdll.c b/tests/tests2/113_btdll.c
new file mode 100644
index 0000000..8ae8981
--- /dev/null
+++ b/tests/tests2/113_btdll.c
@@ -0,0 +1,43 @@
+int tcc_backtrace(const char*, ...);
+#define hello() \
+ tcc_backtrace("hello from %s() / %s:%d",__FUNCTION__,__FILE__,__LINE__)
+
+#ifndef _WIN32
+# define __declspec(n)
+#endif
+
+#if DLL==1
+__declspec(dllexport) int f_1()
+{
+ hello();
+ return 0;
+}
+
+
+#elif DLL==2
+__declspec(dllexport) int f_2()
+{
+ hello();
+ return 0;
+}
+
+
+#else
+
+int f_1();
+int f_2();
+int f_main()
+{
+ hello();
+ return 0;
+}
+
+int main ()
+{
+ f_1();
+ f_2();
+ f_main();
+ return 0;
+}
+
+#endif
diff --git a/tests/tests2/113_btdll.expect b/tests/tests2/113_btdll.expect
new file mode 100644
index 0000000..34de481
--- /dev/null
+++ b/tests/tests2/113_btdll.expect
@@ -0,0 +1,6 @@
+113_btdll.c:12: at f_1: hello from f_1() / 113_btdll.c:12
+113_btdll.c:37: by main
+113_btdll.c:20: at f_2: hello from f_2() / 113_btdll.c:20
+113_btdll.c:38: by main
+113_btdll.c:31: at f_main: hello from f_main() / 113_btdll.c:31
+113_btdll.c:39: by main
diff --git a/tests/tests2/114_bound_signal.c b/tests/tests2/114_bound_signal.c
new file mode 100644
index 0000000..d7d7feb
--- /dev/null
+++ b/tests/tests2/114_bound_signal.c
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <setjmp.h>
+
+/* See tcc-doc.info */
+#if defined(__TINYC__) && __BOUNDS_CHECKING_ON
+#undef __attribute__
+extern void __bound_checking (int no_check);
+#define BOUNDS_CHECKING_OFF __bound_checking(1)
+#define BOUNDS_CHECKING_ON __bound_checking(-1)
+#define BOUNDS_NO_CHECKING __attribute__((bound_no_checking))
+#else
+#define BOUNDS_CHECKING_OFF
+#define BOUNDS_CHECKING_ON
+#define BOUNDS_NO_CHECKING
+#endif
+
+static volatile int run = 1;
+static int dummy[10];
+static sem_t sem;
+
+static void
+add (void) BOUNDS_NO_CHECKING
+{
+ int i;
+
+ for (i = 0; i < (sizeof(dummy)/sizeof(dummy[0])); i++) {
+ dummy[i]++;
+ }
+ /* Should not be translated into __bound_memset */
+ memset (&dummy[0], 0, sizeof(dummy));
+}
+
+static void *
+high_load (void *unused)
+{
+ while (run) {
+ add();
+ }
+ return NULL;
+}
+
+static void *
+do_signal (void *unused)
+{
+ while (run) {
+ kill (getpid(), SIGUSR1);
+ while (sem_wait(&sem) < 0 && errno == EINTR);
+ }
+ return NULL;
+}
+
+static void signal_handler(int sig) BOUNDS_NO_CHECKING
+{
+ add();
+ sem_post (&sem);
+}
+
+int
+main (void)
+{
+ int i;
+ pthread_t id1, id2;
+ struct sigaction act;
+ sigjmp_buf sj;
+ sigset_t m;
+ time_t end;
+
+ memset (&act, 0, sizeof (act));
+ act.sa_handler = signal_handler;
+ act.sa_flags = 0;
+ sigemptyset (&act.sa_mask);
+ sigaction (SIGUSR1, &act, NULL);
+
+ sem_init (&sem, 1, 0);
+ pthread_create(&id1, NULL, high_load, NULL);
+ pthread_create(&id2, NULL, do_signal, NULL);
+
+ printf ("start\n");
+ /* sleep does not work !!! */
+ end = time(NULL) + 2;
+ while (time(NULL) < end) ;
+ run = 0;
+ printf ("end\n");
+
+ pthread_join(id1, NULL);
+ pthread_join(id2, NULL);
+ sem_destroy (&sem);
+
+ sigemptyset (&m);
+ sigprocmask (SIG_SETMASK, &m, NULL);
+ if (sigsetjmp (sj, 0) == 0)
+ {
+ sigaddset (&m, SIGUSR1);
+ sigprocmask (SIG_SETMASK, &m, NULL);
+ siglongjmp (sj, 1);
+ printf ("failed");
+ return 1;
+ }
+ sigprocmask (SIG_SETMASK, NULL, &m);
+ if (!sigismember (&m, SIGUSR1))
+ printf ("failed");
+ return 0;
+}
diff --git a/tests/tests2/114_bound_signal.expect b/tests/tests2/114_bound_signal.expect
new file mode 100644
index 0000000..5d0fb3b
--- /dev/null
+++ b/tests/tests2/114_bound_signal.expect
@@ -0,0 +1,2 @@
+start
+end
diff --git a/tests/tests2/115_bound_setjmp.c b/tests/tests2/115_bound_setjmp.c
new file mode 100644
index 0000000..c402144
--- /dev/null
+++ b/tests/tests2/115_bound_setjmp.c
@@ -0,0 +1,169 @@
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+#define TST int i, a[2], b[2]; \
+ for (i = 0; i < 2; i++) a[i] = 0; \
+ for (i = 0; i < 2; i++) b[i] = 0
+
+static jmp_buf jmp;
+
+static void tst1 (void)
+{
+ TST;
+ longjmp(jmp, 1);
+}
+
+static void tst2(void)
+{
+ jmp_buf jmp;
+
+ setjmp (jmp);
+ TST;
+ tst1();
+}
+
+static void tst3 (jmp_buf loc)
+{
+ TST;
+ longjmp(loc, 1);
+}
+
+static void tst4(jmp_buf loc)
+{
+ jmp_buf jmp;
+
+ setjmp (jmp);
+ TST;
+ tst3(loc);
+}
+
+static void tst (void)
+{
+ jmp_buf loc;
+ static int cnt;
+
+ cnt = 0;
+ if (setjmp (jmp) == 0) {
+ TST;
+ tst2();
+ }
+ else {
+ cnt++;
+ }
+ if (setjmp (loc) == 0) {
+ TST;
+ tst4(loc);
+ }
+ else {
+ cnt++;
+ }
+ if (cnt != 2)
+ printf ("incorrect cnt %d\n", cnt);
+}
+
+static jmp_buf buf1;
+static jmp_buf buf2;
+static int *p;
+static int n_x = 6;
+static int g_counter;
+
+static void stack (void)
+{
+ static int counter;
+ static int way_point1;
+ static int way_point2;
+
+ counter = 0;
+ way_point1 = 3;
+ way_point2 = 2;
+ g_counter = 0;
+ if (setjmp (buf1) != 101) {
+ int a[n_x];
+ g_counter++;
+ p = &a[0];
+ if (g_counter < 5)
+ longjmp (buf1, 2);
+ else if (g_counter == 5)
+ longjmp (buf1, 101);
+ else {
+ setjmp (buf2);
+ longjmp (buf1, 101);
+ }
+ }
+
+ way_point1--;
+
+ if (counter == 0) {
+ counter++;
+ {
+ int a[n_x];
+ g_counter++;
+ p = &a[0];
+ if (g_counter < 5)
+ longjmp (buf1, 2);
+ else if (g_counter == 5)
+ longjmp (buf1, 101);
+ else {
+ setjmp (buf2);
+ longjmp (buf1, 101);
+ }
+ }
+ }
+
+ way_point2--;
+
+ if (counter == 1) {
+ counter++;
+ longjmp (buf2, 2);
+ }
+
+ if (!(way_point1 == 0 && way_point2 == 0 &&
+ g_counter == 6 && counter == 2))
+ printf ("Failed %d %d %d %d\n",
+ way_point1, way_point2, g_counter, counter);
+}
+
+static jmp_buf env;
+static int last_value;
+
+static void jump (int val)
+{
+ longjmp (env, val);
+}
+
+static void check (void)
+{
+ int value;
+
+ last_value = -1;
+ value = setjmp (env);
+ if (value != last_value + 1) {
+ printf ("incorrect value %d %d\n",
+ value, last_value + 1);
+ return;
+ }
+ last_value = value;
+ switch (value) {
+ case 0:
+ jump (0);
+ default:
+ if (value < 10)
+ jump (value + 1);
+ }
+}
+
+int
+main (void)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ tst();
+ stack();
+ check();
+ }
+ return 0;
+}
+
+
diff --git a/tests/tests2/115_bound_setjmp.expect b/tests/tests2/115_bound_setjmp.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/tests2/115_bound_setjmp.expect
diff --git a/tests/tests2/116_bound_setjmp2.c b/tests/tests2/116_bound_setjmp2.c
new file mode 100644
index 0000000..151114d
--- /dev/null
+++ b/tests/tests2/116_bound_setjmp2.c
@@ -0,0 +1,84 @@
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+#if !defined(_WIN32)
+#include <pthread.h>
+#else
+#include <windows.h>
+#endif
+
+#define SIZE 10
+#define COUNT 10
+
+#define TST int i, a[2], b[2]; \
+ for (i = 0; i < 2; i++) a[i] = 0; \
+ for (i = 0; i < 2; i++) b[i] = 0
+
+static int count[SIZE];
+
+static void tst1 (jmp_buf loc)
+{
+ TST;
+ longjmp(loc, 1);
+}
+
+static void tst2(jmp_buf loc)
+{
+ jmp_buf jmp;
+
+ setjmp (jmp);
+ TST;
+ tst1(loc);
+}
+
+static void *tst (void * index)
+{
+ jmp_buf loc;
+ int i = *(int *) index;
+ static int v[SIZE];
+
+ for (v[i] = 0; v[i] < COUNT; v[i]++) {
+ if (setjmp (loc) == 0) {
+ TST;
+ tst2(loc);
+ }
+ else {
+ count[i]++;
+ }
+ i = *(int *) index;
+ }
+ return NULL;
+}
+
+int
+main (void)
+{
+ int i;
+#if !defined(_WIN32)
+ pthread_t id[SIZE];
+#else
+ HANDLE id[SIZE];
+#endif
+ int index[SIZE];
+
+ for (i = 0; i < SIZE; i++) {
+ index[i] = i;
+#if !defined(_WIN32)
+ pthread_create (&id[i], NULL, tst, (void *) &index[i]);
+#else
+ id[i] = CreateThread(NULL, 8192, (LPTHREAD_START_ROUTINE) tst, (void *) &index[i], 0, NULL);
+#endif
+ }
+ for (i = 0; i < SIZE; i++) {
+#if !defined(_WIN32)
+ pthread_join (id[i], NULL);
+#else
+ WaitForSingleObject(id[i], INFINITE);
+#endif
+ }
+ for (i = 0; i < SIZE; i++) {
+ if (count[i] != COUNT)
+ printf ("error: %d %d\n", i, count[i]);
+ }
+ return 0;
+}
diff --git a/tests/tests2/116_bound_setjmp2.expect b/tests/tests2/116_bound_setjmp2.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/tests2/116_bound_setjmp2.expect
diff --git a/tests/tests2/117_gcc_test.c b/tests/tests2/117_gcc_test.c
new file mode 100644
index 0000000..aed62e2
--- /dev/null
+++ b/tests/tests2/117_gcc_test.c
@@ -0,0 +1,158 @@
+#include <stdio.h>
+
+void tst_branch(void)
+{
+ goto *&&a;
+ printf ("dummy");
+a: ;
+}
+
+void tst_void_ptr(void *pv, int i)
+{
+ i ? *pv : *pv; // dr106
+}
+
+void tst_shift(void)
+{
+ int i = 1;
+ long l = 1;
+
+ i = i << 32; // illegal. just test
+ l = l << 64; // illegal. just test
+}
+
+#if !defined(_WIN32)
+#include <sys/mman.h>
+
+void tst_const_addr(void)
+{
+ void *addr = mmap ((void *)0x20000000, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS, -1, 0);
+ if (addr != (void *) -1) {
+#if !defined(__riscv)
+ *(int *)0x20000000 += 42;
+#endif
+ munmap (addr, 4096);
+ }
+}
+#endif
+
+struct zero_struct {};
+
+struct zero_struct tst_zero_struct(void)
+{
+ struct zero_struct ret;
+
+ return ret;
+}
+
+struct big_struct { char a[262144]; };
+
+struct big_struct tst_big(struct big_struct tst)
+{
+ return tst;
+}
+
+void tst_adr (int (*fp)(char *, const char *, ...))
+{
+ char buf[10];
+
+ (*fp)(buf, "%.0f", 5.0);
+}
+
+static const char str[] = "abcdefghijklmnopqrstuvwxyz";
+
+void tst_builtin(void)
+{
+ char *p;
+ char tmp[100];
+
+ if (__builtin_offsetof(struct big_struct, a) != 0) __builtin_abort();
+
+ p = __builtin_memcpy (tmp, str, sizeof(str));
+ if (p != tmp) __builtin_abort();
+
+ if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
+
+ p = __builtin_memmove(tmp, str, sizeof(str));
+ if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
+
+ p = __builtin_memset(tmp, 0, sizeof (tmp));
+ if (p != tmp || tmp[0] != 0 || tmp[99] != 0) __builtin_abort();
+
+ if (__builtin_strlen(str) != sizeof(str) - 1) __builtin_abort();
+
+ p = __builtin_strcpy(tmp, str);
+ if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
+
+ p = __builtin_strncpy(tmp, str, sizeof(str));
+ if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
+
+ if (__builtin_strcmp (p, str)) __builtin_abort();
+
+ if (__builtin_strncmp (p, str, sizeof(str))) __builtin_abort();
+
+ tmp[0] = '\0';
+ p = __builtin_strcat(tmp, str);
+ if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
+
+ if (__builtin_strchr(p, 'z') != &p[25]) __builtin_abort();
+
+ p = __builtin_strdup (str);
+ if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
+ __builtin_free(p);
+
+ p = __builtin_malloc (100);
+ __builtin_memset(p, 0, 100);
+ p = __builtin_realloc (p, 1000);
+ __builtin_memset(p, 0, 1000);
+ __builtin_free(p);
+
+ p = __builtin_calloc(10, 10);
+ __builtin_memset(p, 0, 100);
+ __builtin_free(p);
+
+#if defined(__i386__) || defined(__x86_64__)
+ p = __builtin_alloca(100);
+ __builtin_memset(p, 0, 100);
+#endif
+}
+
+int tst(void)
+{
+ long value = 3;
+ return -value;
+}
+
+void tst_compare(void)
+{
+ /* This failed on risc64 */
+ if (tst() > 0) printf ("error\n");
+}
+
+#pragma pack(1)
+struct S { int d:24; int f:14; } i, j;
+#pragma pack()
+
+void tst_pack (void)
+{
+ i.f = 5; j.f = 5;
+ if (j.f != i.f) printf("error\n");
+}
+
+int
+main (void)
+{
+ struct big_struct big;
+
+ tst_shift();
+ tst_void_ptr(&big.a[0], 0);
+#if !defined(_WIN32)
+ tst_const_addr();
+#endif
+ tst_zero_struct();
+ tst_big(big);
+ tst_adr(&sprintf);
+ tst_builtin();
+ tst_compare();
+ tst_pack();
+}
diff --git a/tests/tests2/117_gcc_test.expect b/tests/tests2/117_gcc_test.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/tests2/117_gcc_test.expect
diff --git a/tests/tests2/11_precedence.c b/tests/tests2/11_precedence.c
index db2049d..845b6bf 100644
--- a/tests/tests2/11_precedence.c
+++ b/tests/tests2/11_precedence.c
@@ -1,4 +1,5 @@
-#include <stdio.h>
+//#include <stdio.h>
+extern int printf(const char *, ...);
int main()
{
diff --git a/tests/tests2/22_floating_point.c b/tests/tests2/22_floating_point.c
index e3491f5..2eb062c 100644
--- a/tests/tests2/22_floating_point.c
+++ b/tests/tests2/22_floating_point.c
@@ -1,6 +1,19 @@
#include <stdio.h>
#include <math.h>
+float fd;
+
+int
+test()
+{
+ // was an internal tcc compiler error with arm64 backend until 2019-11-08
+ if (fd < 5.5) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
int main()
{
// variables
diff --git a/tests/tests2/33_ternary_op.c b/tests/tests2/33_ternary_op.c
index 8579b50..1e6b56d 100644
--- a/tests/tests2/33_ternary_op.c
+++ b/tests/tests2/33_ternary_op.c
@@ -1,4 +1,43 @@
-#include <stdio.h>
+#include <assert.h>
+extern int printf(const char*, ...);
+
+char arr[1];
+static void f (void){}
+void (*fp)(void) = f;
+void call_fp()
+{
+ (fp?f:f)();
+ (fp?fp:fp)();
+ (fp?fp:&f)();
+ (fp?&f:fp)();
+ (fp?&f:&f)();
+ _Generic(0?arr:arr, char*: (void)0);
+ _Generic(0?&arr[0]:arr, char*: (void)0);
+ _Generic(0?arr:&arr[0], char*: (void)0);
+ _Generic(1?arr:arr, char*: (void)0);
+ _Generic(1?&arr[0]:arr, char*: (void)0);
+ _Generic(1?arr:&arr[0], char*: (void)0);
+ _Generic((__typeof(1?f:f)*){0}, void (**)(void): (void)0);
+ (fp?&f:f)();
+ (fp?f:&f)();
+ _Generic((__typeof(fp?0L:(void)0)*){0}, void*: (void)0);
+
+ /* The following line causes a warning */
+ void *xx = fp?f:1;
+}
+
+struct condstruct {
+ int i;
+};
+
+static int getme(struct condstruct* s, int i)
+{
+ int i1 = (i != 0 ? 0 : s)->i;
+ int i2 = (i == 0 ? s : 0)->i;
+ int i3 = (i != 0 ? (void*)0 : s)->i;
+ int i4 = (i == 0 ? s : (void*)0)->i;
+ return i1 + i2 + i3 + i4;
+}
int main()
{
@@ -9,6 +48,32 @@ int main()
printf("%d\n", (Count < 5) ? (Count*Count) : (Count * 3));
}
+ {
+ int c = 0;
+ #define ASSERT(X) assert(X)
+ static struct stru { int x; } a={'A'},b={'B'};
+ static const struct stru2 { int x; } d = { 'D' };
+ ASSERT('A'==(*(1?&a:&b)).x);
+ ASSERT('A'==(1?a:b).x);
+ ASSERT('A'==(c?b:a).x);
+ ASSERT('A'==(0?b:a).x);
+ c=1;
+ ASSERT('A'==(c?a:b).x);
+ ASSERT(sizeof(int) == sizeof(0 ? 'a' : c));
+ ASSERT(sizeof(double) == sizeof(0 ? 'a' : 1.0));
+ ASSERT(sizeof(double) == sizeof(0 ? 0.0 : 'a'));
+ ASSERT(sizeof(float) == sizeof(0 ? 'a' : 1.0f));
+ ASSERT(sizeof(double) == sizeof(0 ? 0.0 : 1.0f));
+ struct condstruct cs = { 38 };
+ printf("%d\n", getme(&cs, 0));
+
+ // the following lines contain type mismatch errors in every ternary expression
+ //printf("comparing double with pointer : size = %d\n", sizeof(0 ? &c : 0.0));
+ //printf("'%c' <> '%c'\n", (0 ? a : d).x, (1 ? a : d).x);
+ //0 ? a : 0.0;
+ }
+
+
return 0;
}
diff --git a/tests/tests2/33_ternary_op.expect b/tests/tests2/33_ternary_op.expect
index 45ea507..497be0e 100644
--- a/tests/tests2/33_ternary_op.expect
+++ b/tests/tests2/33_ternary_op.expect
@@ -1,3 +1,4 @@
+33_ternary_op.c:26: warning: pointer/integer mismatch in conditional expression
0
1
4
@@ -8,3 +9,4 @@
21
24
27
+152
diff --git a/tests/tests2/46_grep.c b/tests/tests2/46_grep.c
index 049dfb1..acda793 100644
--- a/tests/tests2/46_grep.c
+++ b/tests/tests2/46_grep.c
@@ -456,11 +456,13 @@ char *pmatch(char *line, char *pattern)
while (*l && (e = pmatch(l, p)))
l = e; /* Get longest match */
while (*p++ != ENDPAT); /* Skip over pattern */
- while (l >= are) { /* Try to match rest */
+ while (l > are) { /* Try to match rest */
if (e = pmatch(l, p))
return(e);
--l; /* Nope, try earlier */
}
+ if (e = pmatch(l, p))
+ return(e);
return(0); /* Nothing else worked */
default:
diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c
index 0028caf..fd4367a 100644
--- a/tests/tests2/60_errors_and_warnings.c
+++ b/tests/tests2/60_errors_and_warnings.c
@@ -48,4 +48,302 @@ enum rgb3 c = 42;
#elif defined test_74_non_const_init
int i = i++;
+#elif defined test_pointer_assignment
+
+void (*f1)(void);
+void f2(void) {}
+
+struct s1 *ps1;
+struct s2 *ps2;
+
+void *v1, **v2, ***v3;
+
+enum e1 { a = 4 } e10, *e11, *e12;
+enum e2 { b = -4 } e20, *e21;
+enum e3 { c = 5000000000LL } e30;
+
+int *ip;
+unsigned int *up;
+long *lp;
+long long *llp;
+
+char **c1;
+char const **c2;
+unsigned char **u1;
+
+int no_main ()
+{
+ // function
+ f1 = f2;
+ // struct
+ ps1 = ps2;
+ // void*
+ v1 = v3;
+ v2 = v3;
+
+ // enum
+ e11 = e12;
+ e11 = e21;
+ e11 = &e10;
+ ip = &e10;
+ ip = &e20;
+ up = &e10;
+ up = &e20;
+ up = &e30;
+
+ lp = ip;
+ lp = llp;
+
+ // constness
+ c1 = c2;
+ *c1 = *c2;
+ **c1 = **c2;
+
+ // unsigned = signed
+ u1 = c2;
+ *u1 = *c2;
+ **u1 = **c2;
+
+ c2 = c1;
+ *c2 = *c1;
+ **c2 = **c1;
+
+ return 0;
+}
+
+
+#elif defined test_enum_compat
+enum e4;
+enum e5;
+void f3(enum e4 e);
+void f3(enum e5 e);
+
+#elif defined test_enum_compat_2
+enum e6 { E1 = -1, E0 };
+void f3(enum e6);
+void f3(int); // should work as int and e6 are compatible
+void f4(enum e6 e);
+void f4(unsigned e); // should error as unsigned and e6 are incompatible
+
+#elif defined test_ptr_to_str
+void f() { _Generic((int const *[]){0}, int:0); }
+#elif defined test_fnptr_to_str
+void f() { _Generic((int (*(*)(float,char))(double,int)){0}, int:0); }
+#elif defined test_array_to_str
+void f() { _Generic((int(*)[3]){0}, int:0); }
+#elif defined test_duplicate_def_1
+static enum myenum { L = -1 } L;
+#elif defined test_duplicate_def_2
+void foo(void) {
+static enum myenum { L = -1 } L;
+}
+#elif defined test_abstract_decls
+int bar(const char *()); // abstract declarator here is okay
+int bar (const char *(*g)()) // should match this 'g' argument
+{
+ g();
+ return 42;
+}
+int foo(int ()) // abstract decl is wrong in definitions
+{
+ return 0;
+#elif defined test_invalid_1
+void f(char*);
+void g(void) {
+ f((char[]){1, ,});
+}
+#elif defined test_invalid_2
+int ga = 0.42 { 2 };
+#elif defined test_invalid_3
+struct S { int a, b; };
+struct T { struct S x; };
+struct T gt = { 42 a: 1, 43 };
+#elif defined test_invalid_4
+enum E {
+ x = 1 / 0
+};
+#elif defined test_conflicting_types
+int i;
+void foo(void) {
+ int i;
+ {
+ extern double i;
+ i = 42.2;
+ }
+}
+#elif defined test_nested_types
+union u {
+ union u {
+ int i;
+ } m;
+};
+#elif defined test_vla_1
+int X=1;
+
+int main(void) {
+ int t[][][X];
+}
+#elif defined test_invalid_alignas
+/* _Alignas is no type qualifier */
+void * _Alignas(16) p1;
+
+#elif defined test_static_assert
+
+#define ONE 0
+ _Static_assert(ONE == 0, "don't show me this");
+ _Static_assert(ONE == 1, "ONE is not 1");
+
+#elif defined test_static_assert_2
+ _Static_assert(1, "1"" is 1");
+ _Static_assert(0, "0"" is 0");
+
+#elif defined test_static_assert_c2x
+ _Static_assert(1);
+ _Static_assert(0);
+
+#elif defined test_void_array
+ void t[3];
+
+#elif defined test_incomplete_enum_array
+ enum e t[3];
+
+#elif defined test_incomplete_struct_array
+ struct s t[3];
+
+#elif defined test_const_fun_array
+ typedef void f(void);
+ const f t[3];
+
+#elif defined test_incomplete_array_array
+ int t[][3]; // gr: not an error, see below
+
+/******************************************************************/
+#elif defined test_extern_array
+int iii[] = { 1,2,3 };
+extern int iii[];
+int x[];
+int x[2];
+int x[];
+int x[2];
+int x[];
+extern int x[2];
+extern int x[];
+int x[3];
+
+/******************************************************************/
+#elif defined test_func_1 \
+ || defined test_func_2 \
+ || defined test_func_3 \
+ || defined test_func_4 \
+ || defined test_func_5 \
+ || defined test_func_6
+#if defined test_func_1
+int hello(int);
+#elif defined test_func_4
+static int hello(int);
+#endif
+int main () {
+#if defined test_func_6
+ static
+#endif
+ int hello(int);
+ hello(123);
+ return 0;
+}
+int printf(const char*, ...);
+#if defined test_func_3
+static int hello(int a)
+#elif defined test_func_5
+int hello(int a, int b)
+#else
+int hello(int a)
+#endif
+{ printf("%s: a = %d\n", __FUNCTION__, a); return 0; }
+
+/******************************************************************/
+#elif defined test_var_1 \
+ || defined test_var_2 \
+ || defined test_var_3
+#define P(n,v) printf("%-5s: %d ; %d\n", __FUNCTION__, n, v)
+#if defined test_var_1
+int xxx[];
+#endif
+int bar();
+int printf(const char*, ...);
+int main ()
+{
+#if !defined test_var_3
+ int xxx = 2;
+#endif
+ {
+ extern int xxx[
+#if defined test_var_3
+ 2
+#endif
+ ];
+ P(1, xxx[0]);
+ xxx[0] += 2;
+ }
+#if !defined test_var_3
+ P(2, xxx);
+#endif
+ bar(123);
+ return 0;
+}
+int xxx[1] = {1};
+int bar() { P(3, xxx[0]); return 0; }
+
+#elif defined test_var_4
+struct yyy { int y; };
+struct zzz;
+void f1() {
+ extern char *x;
+ extern char **xx;
+ extern struct yyy y;
+ extern struct yyy *yy;
+ extern struct zzz z;
+ extern struct zzz *zz;
+}
+void f2() {
+ extern char *x;
+ extern char **xx;
+ extern struct yyy y;
+ extern struct yyy *yy;
+ extern struct zzz z;
+ extern struct zzz *zz;
+}
+struct yyy y, *yy;
+struct zzz { int z; } z, *zz;
+
+/******************************************************************/
+#elif defined test_long_double_type_for_win32
+
+int main()
+{
+ double *a = 0;
+ long double *b = a;
+ int n = _Generic(*a, double:0, long double:1);
+}
+
+#elif defined test_stray_backslash
+#define x \a
+x
+
+#elif defined test_stray_backslash2
+int printf(const char*, ...);
+int main()
+{
+#define _S(x) #x
+#define S(x) _S(x)
+ printf("%sn\n", S(\\));
+}
+
+/******************************************************************/
+#elif defined test_var_array
+
+static struct var_len { int i; const char str[]; } var_array[] =
+{ { 1, "abcdefghijklmnopqrstuvwxyz" },
+ { 2, "longlonglonglonglong" },
+ { 3, "tst3" } };
+
#endif
diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect
index ed6a690..984e4c1 100644
--- a/tests/tests2/60_errors_and_warnings.expect
+++ b/tests/tests2/60_errors_and_warnings.expect
@@ -20,9 +20,145 @@
60_errors_and_warnings.c:26: error: redefinition of enumerator 'RED'
[test_63_local_enumerator_redefinition]
+[returns 1]
[test_61_undefined_enum]
60_errors_and_warnings.c:46: error: unknown type size
[test_74_non_const_init]
60_errors_and_warnings.c:49: error: initializer element is not constant
+
+[test_pointer_assignment]
+60_errors_and_warnings.c:79: warning: assignment from incompatible pointer type
+60_errors_and_warnings.c:82: warning: assignment from incompatible pointer type
+60_errors_and_warnings.c:86: warning: assignment from incompatible pointer type
+60_errors_and_warnings.c:88: warning: assignment from incompatible pointer type
+60_errors_and_warnings.c:91: warning: assignment from incompatible pointer type
+60_errors_and_warnings.c:92: warning: assignment from incompatible pointer type
+60_errors_and_warnings.c:94: warning: assignment from incompatible pointer type
+60_errors_and_warnings.c:95: warning: assignment from incompatible pointer type
+60_errors_and_warnings.c:98: warning: assignment discards qualifiers from pointer target type
+60_errors_and_warnings.c:99: warning: assignment discards qualifiers from pointer target type
+60_errors_and_warnings.c:103: warning: assignment discards qualifiers from pointer target type
+60_errors_and_warnings.c:104: warning: assignment discards qualifiers from pointer target type
+60_errors_and_warnings.c:109: warning: assignment of read-only location
+
+[test_enum_compat]
+60_errors_and_warnings.c:119: error: incompatible types for redefinition of 'f3'
+
+[test_enum_compat_2]
+60_errors_and_warnings.c:126: error: incompatible types for redefinition of 'f4'
+
+[test_ptr_to_str]
+60_errors_and_warnings.c:129: error: type 'const int **' does not match any association
+
+[test_fnptr_to_str]
+60_errors_and_warnings.c:131: error: type 'int (*(*)(float, char))(double, int)' does not match any association
+
+[test_array_to_str]
+60_errors_and_warnings.c:133: error: type 'int (*)[3]' does not match any association
+
+[test_duplicate_def_1]
+60_errors_and_warnings.c:135: error: redefinition of 'L'
+
+[test_duplicate_def_2]
+60_errors_and_warnings.c:138: error: redeclaration of 'L'
+
+[test_abstract_decls]
+60_errors_and_warnings.c:148: error: identifier expected
+
+[test_invalid_1]
+60_errors_and_warnings.c:153: error: identifier expected
+
+[test_invalid_2]
+60_errors_and_warnings.c:156: error: ';' expected (got "{")
+
+[test_invalid_3]
+60_errors_and_warnings.c:160: error: ',' expected (got "a")
+
+[test_invalid_4]
+60_errors_and_warnings.c:164: error: division by zero in constant
+
+[test_conflicting_types]
+60_errors_and_warnings.c:170: error: incompatible types for redefinition of 'i'
+
+[test_nested_types]
+60_errors_and_warnings.c:177: error: struct/union/enum already defined
+
+[test_vla_1]
+60_errors_and_warnings.c:184: error: need explicit inner array size in VLAs
+
+[test_invalid_alignas]
+60_errors_and_warnings.c:188: error: identifier expected
+
+[test_static_assert]
+60_errors_and_warnings.c:194: error: ONE is not 1
+
+[test_static_assert_2]
+60_errors_and_warnings.c:198: error: 0 is 0
+
+[test_static_assert_c2x]
+60_errors_and_warnings.c:202: error: _Static_assert fail
+
+[test_void_array]
+60_errors_and_warnings.c:205: error: declaration of an array of incomplete type elements
+
+[test_incomplete_enum_array]
+60_errors_and_warnings.c:208: error: declaration of an array of incomplete type elements
+
+[test_incomplete_struct_array]
+60_errors_and_warnings.c:211: error: declaration of an array of incomplete type elements
+
+[test_const_fun_array]
+60_errors_and_warnings.c:215: error: declaration of an array of functions
+
+[test_incomplete_array_array]
+
+[test_extern_array]
+60_errors_and_warnings.c:231: error: incompatible types for redefinition of 'x'
+
+[test_func_1]
+hello: a = 123
+
+[test_func_2]
+hello: a = 123
+
+[test_func_3]
+60_errors_and_warnings.c:261: warning: static storage ignored for redefinition of 'hello'
+hello: a = 123
+
+[test_func_4]
+hello: a = 123
+
+[test_func_5]
+60_errors_and_warnings.c:261: error: incompatible types for redefinition of 'hello'
+
+[test_func_6]
+60_errors_and_warnings.c:249: error: function without file scope cannot be static
+
+[test_var_1]
+main : 1 ; 1
+main : 2 ; 2
+bar : 3 ; 3
+
+[test_var_2]
+main : 1 ; 1
+main : 2 ; 2
+bar : 3 ; 3
+
+[test_var_3]
+60_errors_and_warnings.c:293: error: incompatible types for redefinition of 'xxx'
+
+[test_var_4]
+
+[test_long_double_type_for_win32]
+60_errors_and_warnings.c:324: warning: assignment from incompatible pointer type
+
+[test_stray_backslash]
+60_errors_and_warnings.c:330: error: stray '\' in program
+
+[test_stray_backslash2]
+\n
+
+[test_var_array]
+60_errors_and_warnings.c:345: warning: initializer-string for array is too long
diff --git a/tests/tests2/61_integers.c b/tests/tests2/61_integers.c
new file mode 100644
index 0000000..de29b3c
--- /dev/null
+++ b/tests/tests2/61_integers.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+
+/* This was first introduced to test the ARM port */
+
+#define UINT_MAX ((unsigned) -1)
+
+int main()
+{
+ printf("18/21=%u\n", 18/21);
+ printf("18%%21=%u\n", 18%21);
+ printf("41/21=%u\n", 41/21);
+ printf("41%%21=%u\n", 41%21);
+ printf("42/21=%u\n", 42/21);
+ printf("42%%21=%u\n", 42%21);
+ printf("43/21=%u\n", 43/21);
+ printf("43%%21=%u\n", 43%21);
+ printf("126/21=%u\n", 126/21);
+ printf("126%%21=%u\n", 126%21);
+ printf("131/21=%u\n", 131/21);
+ printf("131%%21=%u\n", 131%21);
+ printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2);
+ printf("(UINT_MAX/2+3)%%2=%u\n", (UINT_MAX/2+3)%2);
+
+ printf("18/-21=%u\n", 18/-21);
+ printf("18%%-21=%u\n", 18%-21);
+ printf("41/-21=%u\n", 41/-21);
+ printf("41%%-21=%u\n", 41%-21);
+ printf("42/-21=%u\n", 42/-21);
+ printf("42%%-21=%u\n", 42%-21);
+ printf("43/-21=%u\n", 43/-21);
+ printf("43%%-21=%u\n", 43%-21);
+ printf("126/-21=%u\n", 126/-21);
+ printf("126%%-21=%u\n", 126%-21);
+ printf("131/-21=%u\n", 131/-21);
+ printf("131%%-21=%u\n", 131%-21);
+ printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2);
+ printf("(UINT_MAX/2+3)%%-2=%u\n", (UINT_MAX/2+3)%-2);
+
+ printf("-18/21=%u\n", -18/21);
+ printf("-18%%21=%u\n", -18%21);
+ printf("-41/21=%u\n", -41/21);
+ printf("-41%%21=%u\n", -41%21);
+ printf("-42/21=%u\n", -42/21);
+ printf("-42%%21=%u\n", -42%21);
+ printf("-43/21=%u\n", -43/21);
+ printf("-43%%21=%u\n", -43%21);
+ printf("-126/21=%u\n", -126/21);
+ printf("-126%%21=%u\n", -126%21);
+ printf("-131/21=%u\n", -131/21);
+ printf("-131%%21=%u\n", -131%21);
+ printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2);
+ printf("-(UINT_MAX/2+3)%%2=%u\n", (0-(UINT_MAX/2+3))%2);
+
+ printf("-18/-21=%u\n", -18/-21);
+ printf("-18%%-21=%u\n", -18%-21);
+ printf("-41/-21=%u\n", -41/-21);
+ printf("-41%%-21=%u\n", -41%-21);
+ printf("-42/-21=%u\n", -42/-21);
+ printf("-42%%-21=%u\n", -42%-21);
+ printf("-43/-21=%u\n", -43/-21);
+ printf("-43%%-21=%u\n", -43%-21);
+ printf("-126/-21=%u\n", -126/-21);
+ printf("-126%%-21=%u\n", -126%-21);
+ printf("-131/-21=%u\n", -131/-21);
+ printf("-131%%-21=%u\n", -131%-21);
+ printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2);
+ printf("-(UINT_MAX/2+3)%%-2=%u\n", (0-(UINT_MAX/2+3))%-2);
+
+ return 0;
+}
diff --git a/tests/tests2/61_integers.expect b/tests/tests2/61_integers.expect
new file mode 100644
index 0000000..22c8d1b
--- /dev/null
+++ b/tests/tests2/61_integers.expect
@@ -0,0 +1,56 @@
+18/21=0
+18%21=18
+41/21=1
+41%21=20
+42/21=2
+42%21=0
+43/21=2
+43%21=1
+126/21=6
+126%21=0
+131/21=6
+131%21=5
+(UINT_MAX/2+3)/2=1073741825
+(UINT_MAX/2+3)%2=0
+18/-21=0
+18%-21=18
+41/-21=4294967295
+41%-21=20
+42/-21=4294967294
+42%-21=0
+43/-21=4294967294
+43%-21=1
+126/-21=4294967290
+126%-21=0
+131/-21=4294967290
+131%-21=5
+(UINT_MAX/2+3)/-2=0
+(UINT_MAX/2+3)%-2=2147483650
+-18/21=0
+-18%21=4294967278
+-41/21=4294967295
+-41%21=4294967276
+-42/21=4294967294
+-42%21=0
+-43/21=4294967294
+-43%21=4294967295
+-126/21=4294967290
+-126%21=0
+-131/21=4294967290
+-131%21=4294967291
+-(UINT_MAX/2+3)/2=1073741823
+-(UINT_MAX/2+3)%2=0
+-18/-21=0
+-18%-21=4294967278
+-41/-21=1
+-41%-21=4294967276
+-42/-21=2
+-42%-21=0
+-43/-21=2
+-43%-21=4294967295
+-126/-21=6
+-126%-21=0
+-131/-21=6
+-131%-21=4294967291
+-(UINT_MAX/2+3)/-2=0
+-(UINT_MAX/2+3)%-2=2147483646
diff --git a/tests/tests2/73_arm64.c b/tests/tests2/73_arm64.c
index 8de61b3..855c476 100644
--- a/tests/tests2/73_arm64.c
+++ b/tests/tests2/73_arm64.c
@@ -230,6 +230,17 @@ void ret(void)
printf("%.1Lf %.1Lf\n", fr_hfa34().a, fr_hfa34().d);
}
+void*
+va_arg_with_struct_ptr(va_list ap) {
+ /*
+ * This was a BUG identified with FFTW-3.3.8 on arm64.
+ * The test case only checks it compiles.
+ */
+ struct X { int _x; };
+ struct X *x = va_arg(ap, struct X *);
+ return x;
+}
+
int match(const char **s, const char *f)
{
const char *p = *s;
diff --git a/tests/tests2/81_types.c b/tests/tests2/81_types.c
index fd6d71b..0bc3bae 100644
--- a/tests/tests2/81_types.c
+++ b/tests/tests2/81_types.c
@@ -39,5 +39,17 @@ int f5 (fptr5 fp, fptr1 i)
{
return fp(i);
}
+typedef int intx4[4];
+int f8 (intx4, int);
int f8 (int ([4]), int);
+int f8 (int y[4], int i)
+{
+ return y[i];
+}
+int f9 (int (*)(int), int);
+int f9 (int ((int)), int);
+int f9 (int f(int), int i)
+{
+ return f(i);
+}
int main () { return 0; }
diff --git a/tests/tests2/82_attribs_position.c b/tests/tests2/82_attribs_position.c
index 7c9f987..fd3f2c4 100644
--- a/tests/tests2/82_attribs_position.c
+++ b/tests/tests2/82_attribs_position.c
@@ -16,4 +16,50 @@ void __attribute__((stdcall)) foo (void)
{
}
-int main () { return 0; }
+#define __stdcall __attribute__((stdcall))
+extern int some_stdcall_func (int, int, int) __stdcall;
+__stdcall int __stdcall some_stdcall_func(int foo, int bar, int baz) {
+ //printf("Hello from stdcall: %i %i %i\n", foo, bar, baz);
+ return 43;
+}
+
+/* The actual attribute isn't important, must just be
+ parsable. */
+#define ATTR __attribute__((__noinline__))
+int ATTR actual_function() {
+ return 42;
+}
+
+extern int printf (const char *, ...);
+static int globalvar;
+int main()
+{
+ void *function_pointer = &actual_function;
+ int localvar = 42, i;
+
+ int a = ((ATTR int(*) (void)) function_pointer)();
+ printf("%i\n", a);
+
+ /* In the following we once misparsed 'ATTR *' is a btype
+ and hence the whole type was garbled. */
+ int b = ( (int(ATTR *)(void)) function_pointer)();
+ printf("%i\n", b);
+
+ /* All these should work and leave the stack pointer in its original
+ position. */
+ some_stdcall_func(1, 10, 100);
+ ((int __stdcall (*)(int, int, int))some_stdcall_func) (2, 20, 200);
+ ((int(*__stdcall)(int, int, int))some_stdcall_func) (3, 30, 300);
+ for (i = 0; i < 1024; i++) {
+ globalvar = i;
+ /* This was once misparsed at <= gitrev 325241c0, forgetting
+ the stdcall attribute on the function pointer leading to
+ stack increment being done twice (in callee and caller).
+ This will clobber 'i' and 'localvar' which is how we detect
+ this. */
+ ((int(__stdcall*)(int, int, int))some_stdcall_func) (4, 40, 400);
+ if (localvar != 42 || globalvar != i)
+ printf("error, localvar=%d i=%d globalvar=%d\n", localvar, i, globalvar);
+ }
+ return 0;
+}
diff --git a/tests/tests2/82_attribs_position.expect b/tests/tests2/82_attribs_position.expect
index e69de29..daaac9e 100644
--- a/tests/tests2/82_attribs_position.expect
+++ b/tests/tests2/82_attribs_position.expect
@@ -0,0 +1,2 @@
+42
+42
diff --git a/tests/tests2/85_asm-outside-function.c b/tests/tests2/85_asm-outside-function.c
index dc5639a..3d7434d 100644
--- a/tests/tests2/85_asm-outside-function.c
+++ b/tests/tests2/85_asm-outside-function.c
@@ -1,6 +1,12 @@
+#ifdef __leading_underscore
+# define _ "_"
+#else
+# define _
+#endif
+
extern int printf (const char *, ...);
extern void vide(void);
-__asm__("vide: ret");
+__asm__(_"vide: ret");
int main() {
vide();
diff --git a/tests/tests2/87_dead_code.c b/tests/tests2/87_dead_code.c
index 98d4566..0d5a64c 100644
--- a/tests/tests2/87_dead_code.c
+++ b/tests/tests2/87_dead_code.c
@@ -26,6 +26,36 @@ static void kb_wait_1(void)
timeout--;
} while (timeout);
}
+
+static int global;
+
+static void foo(int i)
+{
+ global+=i;
+ printf ("g=%d\n", global);
+}
+
+static int check(void)
+{
+ printf ("check %d\n", global);
+ return 1;
+}
+
+static void dowhile(void)
+{
+ do {
+ foo(1);
+ if (global == 1) {
+ continue;
+ } else if (global == 2) {
+ continue;
+ }
+ /* The following break shouldn't disable the check() call,
+ as it's reachable by the continues above. */
+ break;
+ } while (check());
+}
+
int main (void)
{
int i = 1;
@@ -118,5 +148,8 @@ enterloop3:
printf ("error4\n");
}
}
+
+ dowhile();
+
return 0;
}
diff --git a/tests/tests2/87_dead_code.expect b/tests/tests2/87_dead_code.expect
index 0b3ec1d..a8c93bd 100644
--- a/tests/tests2/87_dead_code.expect
+++ b/tests/tests2/87_dead_code.expect
@@ -16,3 +16,8 @@ once3
twice3
caseok
caseok2
+g=1
+check 1
+g=2
+check 2
+g=3
diff --git a/tests/tests2/88_codeopt.c b/tests/tests2/88_codeopt.c
index 647626f..2ab4c8a 100644
--- a/tests/tests2/88_codeopt.c
+++ b/tests/tests2/88_codeopt.c
@@ -1,7 +1,7 @@
/* Check some way in where code suppression caused various
miscompilations. */
extern int printf (const char *, ...);
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
size_t _brk_start, _brk_end;
void * extend_brk(size_t size, size_t align)
@@ -51,6 +51,7 @@ _Bool chk(unsigned long addr, unsigned long limit, unsigned long size)
only with certain internal checking added that's not committed). */
if (0)
ret = 0 != (!!(addr > limit - size));
+ return 0;
}
int main()
diff --git a/tests/tests2/90_struct-init.c b/tests/tests2/90_struct-init.c
index d931e23..ade7fad 100644
--- a/tests/tests2/90_struct-init.c
+++ b/tests/tests2/90_struct-init.c
@@ -87,6 +87,13 @@ union UV guv = {{6,5}};
union UV guv2 = {{.b = 7, .a = 8}};
union UV guv3 = {.b = 8, .a = 7};
+struct SSU {
+ int y;
+ struct { int x; };
+};
+struct SSU gssu1 = { .y = 5, .x = 3 };
+struct SSU gssu2 = { 5, 3 };
+
/* Under -fms-extensions also the following is valid:
union UV2 {
struct Anon {u8 a,b;}; // unnamed member, but tagged struct, ...
@@ -166,6 +173,14 @@ void foo (struct W *w, struct pkthdr *phdr_)
int elt = 0x42;
/* Range init, overlapping */
struct T lt2 = { { [1 ... 5] = 9, [6 ... 10] = elt, [4 ... 7] = elt+1 }, 1 };
+ struct SSU lssu1 = { 5, 3 };
+ struct SSU lssu2 = { .y = 5, .x = 3 };
+ /* designated initializers in GNU form */
+#if defined(__GNUC__) || defined(__TINYC__)
+ struct S ls4 = {a: 1, b: 2, c: {3, 4}};
+#else
+ struct S ls4 = {.a = 1, .b = 2, .c = {3, 4}};
+#endif
print(ls);
print(ls2);
print(lt);
@@ -182,7 +197,10 @@ void foo (struct W *w, struct pkthdr *phdr_)
print(lv2);
print(lv3);
print(lt2);
+ print(lssu1);
+ print(lssu2);
print(flow);
+ print(ls4);
}
#endif
@@ -272,6 +290,8 @@ int main()
print(guv.b);
print(guv2);
print(guv3);
+ print(gssu1);
+ print(gssu2);
print(phdr);
foo(&gw, &phdr);
//printf("q: %s\n", q);
diff --git a/tests/tests2/90_struct-init.expect b/tests/tests2/90_struct-init.expect
index e366121..c55cb47 100644
--- a/tests/tests2/90_struct-init.expect
+++ b/tests/tests2/90_struct-init.expect
@@ -17,6 +17,8 @@ guv: 6 5 0 0
guv.b: 5
guv2: 8 7 0 0
guv3: 7 8 0 0
+gssu1: 5 0 0 0 3 0 0 0
+gssu2: 5 0 0 0 3 0 0 0
phdr: 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0
ls: 1 2 3 4
ls2: 1 2 3 4
@@ -34,7 +36,10 @@ lv: 3 4 5 6 68 61 68 61 0 0 0 0 0 0 0 0 0 0 0 0 2d 2e
lv2: 1 2 3 4 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30
lv3: 7 8 9 a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32
lt2: 0 9 9 9 43 43 43 43 42 42 42 0 0 0 0 0 1
+lssu1: 5 0 0 0 3 0 0 0
+lssu2: 5 0 0 0 3 0 0 0
flow: 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0
+ls4: 1 2 3 4
one
two
three
diff --git a/tests/tests2/92_enum_bitfield.c b/tests/tests2/92_enum_bitfield.c
index bb6dc35..fb8f7a3 100644
--- a/tests/tests2/92_enum_bitfield.c
+++ b/tests/tests2/92_enum_bitfield.c
@@ -45,6 +45,7 @@ int convert_like_real (tree convs)
break;
};
printf("unsigned enum bit-fields broken\n");
+ return 0;
}
int main()
diff --git a/tests/tests2/94_generic.c b/tests/tests2/94_generic.c
index d7fb5fc..6e85c02 100644
--- a/tests/tests2/94_generic.c
+++ b/tests/tests2/94_generic.c
@@ -20,6 +20,12 @@ int b_f()
return 10;
}
+typedef int (*fptr)(int);
+int foo(int i)
+{
+ return i;
+}
+
typedef int int_type1;
#define gen_sw(a) _Generic(a, const char *: 1, default: 8, int: 123);
@@ -60,5 +66,50 @@ int main()
long long: "long long"));
i = _Generic(l, long: 1, int: 2);
printf("%d\n", i);
+ i = _Generic(foo, fptr: 3, int: 4);
+ printf("%d\n", i);
+
+ (void)_Generic((int(*)[2]){0}, int(*)[2]:0, int(*)[4]:0); //shouldn't match twice
+
+ //should accept ({ }) in the controlling expr of _Generic even in const_wanted contexts
+ struct { _Bool x_0: _Generic(({0;}),default:1); } my_x;
+
+ _Generic((__typeof((float const)((float const){42}))*){0}, float*: 0); //casts lose top-level qualifiers
+ int const x = 42; __typeof((__typeof(x))x) *xp = 0; (void)_Generic(xp, int*: 0); //casts lose top-level qualifiers
+
+ //TEST TERNARY:
+ //Same type
+ _Generic( 0?(long*)0:(long*)0, long*: (void)0);
+ //combining of qualifiers
+ _Generic( 0?(long volatile*)0:(long const*)0, long const volatile*: (void)0);
+ //nul-ptr constant selects other type
+ _Generic( 0?(long*)0:0, long*: (void)0);
+ _Generic( 0?(long*)0:(void*)0, long*: (void)0);
+
+ //void ptrs get chosen preferentially; qualifs still combine
+ _Generic( 0?(int volatile*)0: (void const*)1, void volatile const*: (void)0);
+ //like gcc but not clang, don't treat (void* const as the null-ptr constant)
+ _Generic( 0?(int volatile*)0: (void const*)0, void volatile const*: (void)0);
+
+ //ptrs to incomplete types get completed
+ (void)(sizeof(struct { int x:_Generic( 0?(int (*)[4])0 : (int (*)[])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
+ (void)(sizeof(struct { int x:_Generic( 0?(int (*)[])0 : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
+
+ {
+ /* completion shouldn't affect the type of decl */
+ char **argv;
+ _Generic(argv, char**: (void)0);
+ _Generic(0?(char const*)0:argv[0], char const*: (void)0);
+ _Generic(argv, char**: (void)0);
+ }
+ {
+ extern int (*ar)[];
+ (void)(sizeof(struct { int x:_Generic( 0?(int (*)[4])0 : (int (*)[])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
+ (void)(sizeof(struct { int x:_Generic( 0?(int (*)[])0 : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
+ (void)(sizeof(struct { int x:_Generic( 0?ar : (int (*)[4])0, int (*)[4]:+1, int (*)[5]:(void)0); }));
+ (void)(sizeof(struct { int x:_Generic( 0?(int (*)[4])0 : ar, int (*)[4]:+1, int (*)[5]:(void)0); }));
+ (void)(sizeof(struct { int x:_Generic( 0?(int (*)[5])0 : ar, int (*)[5]:+1, int (*)[4]:(void)0); }));
+ }
+
return 0;
}
diff --git a/tests/tests2/94_generic.expect b/tests/tests2/94_generic.expect
index 9aa9275..748d78f 100644
--- a/tests/tests2/94_generic.expect
+++ b/tests/tests2/94_generic.expect
@@ -10,4 +10,5 @@
3
4
long
-1 \ No newline at end of file
+1
+3
diff --git a/tests/tests2/95_bitfields.c b/tests/tests2/95_bitfields.c
index f025c57..4ac38da 100644
--- a/tests/tests2/95_bitfields.c
+++ b/tests/tests2/95_bitfields.c
@@ -78,6 +78,27 @@
}
/* ----------------------------------------------------------------------- */
+#elif TEST == 7
+{
+#ifdef _WIN32
+ typedef long long int ll;
+#else
+ typedef long int ll;
+#endif
+ struct M P __s {
+ ll d : 16;
+ ll b : 16;
+ ll x : 16;
+ ll y : 1;
+ ll z : 2;
+ ll a : 11;
+ ll e : 1;
+ ll f : 1;
+ };
+ TEST_STRUCT(1,2,3,4,5);
+}
+
+/* ----------------------------------------------------------------------- */
#elif defined PACK
#if PACK
@@ -101,6 +122,8 @@ top = 0;
#include SELF
#define TEST 6
#include SELF
+#define TEST 7
+#include SELF
#if PACK
# pragma pack(pop)
diff --git a/tests/tests2/95_bitfields.expect b/tests/tests2/95_bitfields.expect
index 6a8fd9a..215055d 100644
--- a/tests/tests2/95_bitfields.expect
+++ b/tests/tests2/95_bitfields.expect
@@ -34,6 +34,12 @@ bits as set : 00000030002001FD00000004
values : 01 02 03 04 fffffffd
align/size : 4 12
+---- TEST 7 ----
+bits in use : 3FFFFFFFFFFF0000
+bits as set : 0026000100050000
+values : 01 00 ffffffff 04 05
+align/size : 8 8
+
---- TEST 1 - PACKED ----
@@ -72,6 +78,12 @@ bits as set : 0030002001FD00000004
values : 01 02 03 04 fffffffd
align/size : 1 10
+---- TEST 7 - PACKED ----
+bits in use : 3FFFFFFFFFFF0000
+bits as set : 0026000100050000
+values : 01 00 ffffffff 04 05
+align/size : 1 8
+
---- TEST 1 - WITH ALIGN ----
@@ -110,6 +122,12 @@ bits as set : 00000030002001FD00000004
values : 01 02 03 04 fffffffd
align/size : 4 12
+---- TEST 7 - WITH ALIGN ----
+bits in use : 3FFFFFFFFFFF0000
+bits as set : 0026000100050000
+values : 01 00 ffffffff 04 05
+align/size : 8 8
+
---- TEST 1 - PACKED - WITH ALIGN ----
@@ -147,3 +165,9 @@ bits in use : 007000FFFFFFFFFFFFFF
bits as set : 0030002001FD00000004
values : 01 02 03 04 fffffffd
align/size : 1 10
+
+---- TEST 7 - PACKED - WITH ALIGN ----
+bits in use : 3FFFFFFFFFFF0000
+bits as set : 0026000100050000
+values : 01 00 ffffffff 04 05
+align/size : 1 8
diff --git a/tests/tests2/95_bitfields_ms.expect b/tests/tests2/95_bitfields_ms.expect
index 8ccafb7..97c46be 100644
--- a/tests/tests2/95_bitfields_ms.expect
+++ b/tests/tests2/95_bitfields_ms.expect
@@ -34,6 +34,12 @@ bits as set : 000000000000003000002001000000FD00000004
values : 01 02 03 04 fffffffd
align/size : 4 20
+---- TEST 7 - MS-BITFIELDS ----
+bits in use : 3FFFFFFFFFFF0000
+bits as set : 0026000100050000
+values : 0000000000000001 0000000000000000 ffffffffffffffff 0000000000000004 0000000000000005
+align/size : 8 8
+
---- TEST 1 - MS-BITFIELDS - PACKED ----
@@ -72,6 +78,12 @@ bits as set : 000000003000002001FD00000004
values : 01 02 03 04 fffffffd
align/size : 1 14
+---- TEST 7 - MS-BITFIELDS - PACKED ----
+bits in use : 3FFFFFFFFFFF0000
+bits as set : 0026000100050000
+values : 0000000000000001 0000000000000000 ffffffffffffffff 0000000000000004 0000000000000005
+align/size : 1 8
+
---- TEST 1 - MS-BITFIELDS - WITH ALIGN ----
@@ -110,6 +122,12 @@ bits as set : 000000000000003000002001000000FD00000004
values : 01 02 03 04 fffffffd
align/size : 4 20
+---- TEST 7 - MS-BITFIELDS - WITH ALIGN ----
+bits in use : 3FFFFFFFFFFF0000
+bits as set : 0026000100050000
+values : 0000000000000001 0000000000000000 ffffffffffffffff 0000000000000004 0000000000000005
+align/size : 8 8
+
---- TEST 1 - MS-BITFIELDS - PACKED - WITH ALIGN ----
@@ -147,3 +165,9 @@ bits in use : 00000000700000FFFFFFFFFFFFFF
bits as set : 000000003000002001FD00000004
values : 01 02 03 04 fffffffd
align/size : 1 14
+
+---- TEST 7 - MS-BITFIELDS - PACKED - WITH ALIGN ----
+bits in use : 3FFFFFFFFFFF0000
+bits as set : 0026000100050000
+values : 0000000000000001 0000000000000000 ffffffffffffffff 0000000000000004 0000000000000005
+align/size : 1 8
diff --git a/tests/tests2/96_nodata_wanted.c b/tests/tests2/96_nodata_wanted.c
index cc211d3..790b431 100644
--- a/tests/tests2/96_nodata_wanted.c
+++ b/tests/tests2/96_nodata_wanted.c
@@ -55,11 +55,10 @@ te0:;
static char ds1 = 0;
ts1:;
if (!SKIP) {
- static void *p = (void*)&main;
- static char cc[] = "static string";
- static double d = 8.0;
-
- static struct __attribute__((packed)) {
+ void *p = (void*)&main;
+ char cc[] = "static string";
+ double d = 8.0;
+ struct __attribute__((packed)) {
unsigned x : 12;
unsigned char y : 7;
unsigned z : 28, a: 4, b: 5;
@@ -81,4 +80,19 @@ te1:;
/*printf("# %d/%d\n", dl, tl);*/
}
+#elif defined test_static_data
+
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+ goto there;
+ if (0) {
+ static int a = 1;
+ printf("hello\n"); /* the "hello\n" string is still suppressed */
+there:
+ printf("a = %d\n", a);
+ }
+ return 0;
+}
+
#endif
diff --git a/tests/tests2/96_nodata_wanted.expect b/tests/tests2/96_nodata_wanted.expect
index 2749109..92dc9c4 100644
--- a/tests/tests2/96_nodata_wanted.expect
+++ b/tests/tests2/96_nodata_wanted.expect
@@ -9,7 +9,7 @@
[test_local_data_noerror]
96_nodata_wanted.c:25: warning: assignment makes integer from pointer without a cast
-96_nodata_wanted.c:25: warning: nonportable conversion from pointer to char/short
+96_nodata_wanted.c:25: warning: cast between pointer and integer of different size
[test_data_suppression_off]
data:
@@ -21,3 +21,6 @@ size of data/text:
[test_data_suppression_on]
size of data/text:
zero/zero
+
+[test_static_data]
+a = 1
diff --git a/tests/tests2/98_al_ax_extend.c b/tests/tests2/98_al_ax_extend.c
index 9b4e02f..1cd6585 100644
--- a/tests/tests2/98_al_ax_extend.c
+++ b/tests/tests2/98_al_ax_extend.c
@@ -8,7 +8,7 @@ asm (
"ret;"
);
-#if 1
+#ifndef __leading_underscore
#define us _us
#define ss _ss
#define uc _uc
diff --git a/tests/tests2/99_fastcall.c b/tests/tests2/99_fastcall.c
index ee4b67d..8fbc904 100644
--- a/tests/tests2/99_fastcall.c
+++ b/tests/tests2/99_fastcall.c
@@ -5,7 +5,7 @@
#define __fastcall __attribute((fastcall))
#endif
-#if 1
+#ifndef __leading_underscore
#define SYMBOL(x) _##x
#else
#define SYMBOL(x) x
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
index 190b2d9..8b169b4 100644
--- a/tests/tests2/Makefile
+++ b/tests/tests2/Makefile
@@ -3,7 +3,9 @@ include $(TOP)/Makefile
SRC = $(TOPSRC)/tests/tests2
VPATH = $(SRC)
-TESTS = $(patsubst %.c,%.test,$(sort $(notdir $(wildcard $(SRC)/*.c))))
+TESTS = $(patsubst %.c,%.test,\
+ $(sort $(notdir $(wildcard $(SRC)/??_*.c)))\
+ $(sort $(notdir $(wildcard $(SRC)/???_*.c))))
# some tests do not pass on all platforms, remove them for now
SKIP = 34_array_assignment.test # array assignment is not in C standard
@@ -12,7 +14,7 @@ ifeq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
endif
ifdef CONFIG_OSX
SKIP += 40_stdio.test 42_function_pointer.test
- FLAGS += -w
+ SKIP += 113_btdll.test # no shared lib support yet
endif
ifeq ($(ARCH),x86_64)
SKIP += 73_arm64.test
@@ -21,7 +23,17 @@ ifeq (,$(filter i386,$(ARCH)))
SKIP += 98_al_ax_extend.test 99_fastcall.test
endif
ifeq (,$(filter i386 x86_64,$(ARCH)))
- SKIP += 85_asm-outside-function.test
+ SKIP += 85_asm-outside-function.test # x86 asm
+ SKIP += 113_btdll.test # dll support needed
+endif
+ifeq (,$(filter i386 x86_64 arm arm64 riscv64,$(ARCH)))
+ SKIP += 112_backtrace.test
+ SKIP += 114_bound_signal.test
+ SKIP += 115_bound_setjmp.test
+ SKIP += 116_bound_setjmp2.test
+endif
+ifeq (-$(CONFIG_musl)-,-yes-)
+ SKIP += 112_backtrace.test
endif
ifeq (-$(findstring gcc,$(CC))-,--)
SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS))
@@ -29,6 +41,10 @@ endif
ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-)
SKIP += 95_bitfields%.test # type_align is different on 32bit-non-windows
endif
+ifeq (-$(CONFIG_WIN32)-,-yes-)
+ SKIP += 106_pthread.test # No pthread support
+ SKIP += 114_bound_signal.test # No pthread support
+endif
# Some tests might need arguments
ARGS =
@@ -54,21 +70,47 @@ GEN-ALWAYS =
# using the ms compiler for the really ms-compatible bitfields
95_bitfields_ms.test : GEN = $(GEN-MSC)
+# this test compiles/links two files:
+104_inline.test : FLAGS += $(subst 104,104+,$1)
+104_inline.test : GEN = $(GEN-TCC)
+
+# this test needs pthread
+106_pthread.test: FLAGS += -pthread
+106_pthread.test: NORUN = true
+
+# constructor/destructor
+108_constructor.test: NORUN = true
+
+112_backtrace.test: FLAGS += -dt -b
+112_backtrace.test 113_btdll.test: FILTER += \
+ -e 's;[0-9A-Fa-fx]\{5,\};........;g' \
+ -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g'
+
+# this test creates two DLLs and an EXE
+113_btdll.test: NORUN = true
+113_btdll.test: FLAGS += \
+ -bt $1 -shared -D DLL=1 -o a1$(DLLSUF) && $(TCC) \
+ -bt $1 -shared -D DLL=2 -o a2$(DLLSUF) && $(TCC) \
+ -bt a1$(DLLSUF) a2$(DLLSUF) -Wl,-rpath=.
+
+114_bound_signal.test: FLAGS += -b
+115_bound_setjmp.test: FLAGS += -b
+116_bound_setjmp2.test: FLAGS += -b
+
+117_gcc_test.test: FLAGS += $(T2) && $(TCC) -b
+
# Filter source directory in warnings/errors (out-of-tree builds)
-FILTER = 2>&1 | sed 's,$(SRC)/,,g'
-# Filter some always-warning
-ifeq (-$(findstring arm,$(ARCH))-,-arm-)
-FILTER += 2>&1 | grep -v 'warning: soft float ABI currently not supported'
-endif
+FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
-all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ;
+all test tests2.all: $(filter-out $(SKIP),$(TESTS))
+ @$(MAKE) clean --no-print-directory -s
%.test: %.c %.expect
@echo Test: $*...
- @$(if $(NORUN),$(T1),$(T2)) $(if $(NODIFF),,$(T3))
+ @$(call T1,$<) $(T3)
-T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS)
-T2 = $(TCC) $(FLAGS) -run $< $(ARGS)
+T1 = $(TCC) $(FLAGS) $(T2) $(ARGS)
+T2 = $(if $(NORUN),$1 -o a.exe && ./a.exe,-run $1)
T3 = $(FILTER) >$*.output 2>&1 || true \
&& diff -Nbu $(filter %.expect,$^) $*.output \
&& rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS))
@@ -79,7 +121,7 @@ tests2.%+:
# just run tcc to see the output, e.g. "make tests2.37-"
tests2.%-:
- @$(MAKE) $(call F1,$*) NODIFF=true --no-print-directory
+ @$(MAKE) $(call F1,$*) T3= --no-print-directory
# run single test, e.g. "make tests2.37"
tests2.%:
@@ -95,9 +137,9 @@ F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)"
@rm -f *.exe *.obj *.pdb
# using TCC for .expect if -dt in FLAGS
-GEN = $(if $(filter -dt,$(FLAGS)),$(GEN-TCC),$(GEN-CC))
+GEN = $(if $(filter -dt -bt -b,$(FLAGS)),$(GEN-TCC),$(GEN-CC))
GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o a.exe && ./a.exe $(ARGS)
-GEN-TCC = $(TCC) $(FLAGS) -run $1 $(ARGS)
+GEN-TCC = $(T1)
GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe
MS-CC = cl
@@ -108,5 +150,5 @@ MS-CC = cl
$(sort $(GEN-ALWAYS) $(UPDATE)) : force
force:
-clean:
- rm -f fred.txt *.output a.exe $(GEN-ALWAYS)
+clean :
+ rm -f fred.txt *.output a.exe *.dll *.so *.def $(GEN-ALWAYS)