summaryrefslogtreecommitdiff
path: root/support/valdiag
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /support/valdiag
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'support/valdiag')
-rw-r--r--support/valdiag/Makefile54
-rw-r--r--support/valdiag/Makefile.in54
-rw-r--r--support/valdiag/tests/bug-2773.c17
-rw-r--r--support/valdiag/tests/bug-895992.c34
-rw-r--r--support/valdiag/tests/bug-971834.c49
-rw-r--r--support/valdiag/tests/cflow.c26
-rw-r--r--support/valdiag/tests/const.c21
-rw-r--r--support/valdiag/tests/constantRange.c267
-rw-r--r--support/valdiag/tests/declafterstmt.c45
-rw-r--r--support/valdiag/tests/enum.c89
-rw-r--r--support/valdiag/tests/funcdec.c48
-rw-r--r--support/valdiag/tests/overflow.c61
-rw-r--r--support/valdiag/tests/pointers.c21
-rw-r--r--support/valdiag/tests/primtypes.c100
-rw-r--r--support/valdiag/tests/restrict.c63
-rw-r--r--support/valdiag/tests/static_assert.c19
-rw-r--r--support/valdiag/tests/struct.c115
-rw-r--r--support/valdiag/tests/structflexiblearray.c24
-rw-r--r--support/valdiag/tests/switch.c158
-rw-r--r--support/valdiag/tests/tentdecl.c127
-rw-r--r--support/valdiag/tests/typedef.c45
-rw-r--r--support/valdiag/valdiag.py397
22 files changed, 1834 insertions, 0 deletions
diff --git a/support/valdiag/Makefile b/support/valdiag/Makefile
new file mode 100644
index 0000000..af97388
--- /dev/null
+++ b/support/valdiag/Makefile
@@ -0,0 +1,54 @@
+.SILENT:
+
+PYTHON = python3.6
+
+srcdir = .
+top_srcdir = ../..
+top_builddir = ../..
+
+TESTS_DIR = $(srcdir)/tests
+RESULTS_DIR = results
+PORTS_DIR = $(srcdir)/ports
+BUILD_DIR = gen
+ALL_PORTS = mcs51 mcs51-large mcs51-stack-auto ds390 z80 z180 r2k gbz80 tlcs90 hc08 s08 stm8 pdk14
+
+ALL_TESTS = $(shell find $(TESTS_DIR) -name "*.c")
+
+PORT_RESULTS_DIR = $(RESULTS_DIR)/$(PORT)
+PORT_RESULTS = $(ALL_TESTS:$(TESTS_DIR)/%.c=$(PORT_RESULTS_DIR)/%.out)
+PORT_BUILD_DIR = $(BUILD_DIR)/$(PORT)
+
+all: test-ports
+
+test-ports:
+ for i in $(ALL_PORTS); do $(MAKE) test-port PORT=$$i; done
+
+test-mcs51:
+ $(MAKE) test-port PORT=mcs51
+
+test-port: port-results
+
+clean: clean-gen
+ rm -rf $(RESULTS_DIR) *.pyc
+ rm -rf $(BUILD_DIR)
+
+distclean: clean
+ rm -r Makefile
+
+clean-gen:
+ for i in $(ALL_PORTS); do $(MAKE) clean-port PORT=$$i; done
+
+clean-port:
+ rm -rf $(PORT_BUILD_DIR)
+
+$(PORT_RESULTS_DIR)/%.out: $(TESTS_DIR)/%.c
+ $(PYTHON) $(srcdir)/valdiag.py $(PORT) $< $(PORT_BUILD_DIR)/$* $(srcdir)/../../device/include > $@
+ grep FAIL $@ ; true
+ cat $@ | $(PYTHON) $(srcdir)/../regression/compact-results.py
+
+port-results: port-dirs $(PORT_RESULTS)
+ cat $(PORT_RESULTS) | $(PYTHON) $(srcdir)/../regression/collate-results.py $(PORT)
+
+port-dirs:
+ mkdir -p $(PORT_RESULTS_DIR)
+ mkdir -p $(PORT_BUILD_DIR)
diff --git a/support/valdiag/Makefile.in b/support/valdiag/Makefile.in
new file mode 100644
index 0000000..732de5f
--- /dev/null
+++ b/support/valdiag/Makefile.in
@@ -0,0 +1,54 @@
+.SILENT:
+
+PYTHON = @PYTHON@
+VPATH = @srcdir@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
+
+TESTS_DIR = $(srcdir)/tests
+RESULTS_DIR = results
+PORTS_DIR = $(srcdir)/ports
+BUILD_DIR = gen
+ALL_PORTS = mcs51 mcs51-large mcs51-stack-auto ds390 z80 z180 r2k gbz80 tlcs90 hc08 s08 stm8 pdk14
+
+ALL_TESTS = $(shell find $(TESTS_DIR) -name "*.c")
+
+PORT_RESULTS_DIR = $(RESULTS_DIR)/$(PORT)
+PORT_RESULTS = $(ALL_TESTS:$(TESTS_DIR)/%.c=$(PORT_RESULTS_DIR)/%.out)
+PORT_BUILD_DIR = $(BUILD_DIR)/$(PORT)
+
+all: test-ports
+
+test-ports:
+ for i in $(ALL_PORTS); do $(MAKE) test-port PORT=$$i; done
+
+test-mcs51:
+ $(MAKE) test-port PORT=mcs51
+
+test-port: port-results
+
+clean: clean-gen
+ rm -rf $(RESULTS_DIR) *.pyc
+ rm -rf $(BUILD_DIR)
+
+distclean: clean
+ rm -r Makefile
+
+clean-gen:
+ for i in $(ALL_PORTS); do $(MAKE) clean-port PORT=$$i; done
+
+clean-port:
+ rm -rf $(PORT_BUILD_DIR)
+
+$(PORT_RESULTS_DIR)/%.out: $(TESTS_DIR)/%.c
+ $(PYTHON) $(srcdir)/valdiag.py $(PORT) $< $(PORT_BUILD_DIR)/$* $(srcdir)/../../device/include > $@
+ grep FAIL $@ ; true
+ cat $@ | $(PYTHON) $(srcdir)/../regression/compact-results.py
+
+port-results: port-dirs $(PORT_RESULTS)
+ cat $(PORT_RESULTS) | $(PYTHON) $(srcdir)/../regression/collate-results.py $(PORT)
+
+port-dirs:
+ mkdir -p $(PORT_RESULTS_DIR)
+ mkdir -p $(PORT_BUILD_DIR)
diff --git a/support/valdiag/tests/bug-2773.c b/support/valdiag/tests/bug-2773.c
new file mode 100644
index 0000000..7ccf7ab
--- /dev/null
+++ b/support/valdiag/tests/bug-2773.c
@@ -0,0 +1,17 @@
+/* bug-2773.c
+
+ Missing diagnostic on duplicate paramter name
+ */
+
+#ifdef TEST1
+extern void *h2 (int g2, int g2); /* ERROR */
+#endif
+
+#ifdef TEST2
+int i;
+
+extern void *h (int g, int g) { /* ERROR */
+ i = g;
+}
+#endif
+
diff --git a/support/valdiag/tests/bug-895992.c b/support/valdiag/tests/bug-895992.c
new file mode 100644
index 0000000..24bf327
--- /dev/null
+++ b/support/valdiag/tests/bug-895992.c
@@ -0,0 +1,34 @@
+
+/* bug-895992.c
+
+ Life Range problem with
+ - uninitialized variable
+ - loop
+ - conditional block
+ */
+
+#ifdef TEST1
+char p0;
+
+void wait (void);
+
+void foo(void)
+{
+ unsigned char number;
+ unsigned char start = 1;
+ unsigned char i;
+
+ do
+ {
+ for (i = 1; i > 0 ; i--)
+ wait();
+ if (start)
+ {
+ number = p0;
+ start = 0;
+ }
+ number--; /* WARNING(SDCC) */
+ }
+ while (number != 0);
+}
+#endif
diff --git a/support/valdiag/tests/bug-971834.c b/support/valdiag/tests/bug-971834.c
new file mode 100644
index 0000000..27df123
--- /dev/null
+++ b/support/valdiag/tests/bug-971834.c
@@ -0,0 +1,49 @@
+
+/* bug-971834.c
+
+ Life Range problem with
+ - uninitialized variable
+ - loop
+ */
+
+#ifdef TEST1
+unsigned char ttt = 2;
+
+short foo (void)
+{
+ unsigned short a;
+ a |= ttt; /* WARNING(SDCC || GCC) */
+ return a;
+}
+#endif
+
+
+#ifdef TEST2
+unsigned char ttt[] = {0xff, 1};
+
+char foo (void)
+{
+ unsigned char a, i;
+ for (i = 0; i < sizeof(ttt); i++)
+ a |= ttt[i]; /* WARNING(SDCC) */
+ return a;
+}
+#endif
+
+#ifdef TEST3
+unsigned char ttt[] = {0xff, 1};
+unsigned char b;
+
+char foo (void)
+{
+ unsigned char i, j;
+ unsigned char a;
+ for (j = 0; j < sizeof(ttt); j++) {
+ for (i = 0; i < sizeof(ttt); i++) {
+ a |= ttt[i]; /* WARNING(SDCC) */
+ b = a;
+ }
+ }
+ return b;
+}
+#endif
diff --git a/support/valdiag/tests/cflow.c b/support/valdiag/tests/cflow.c
new file mode 100644
index 0000000..b584550
--- /dev/null
+++ b/support/valdiag/tests/cflow.c
@@ -0,0 +1,26 @@
+
+int x;
+
+#ifdef TEST0
+void foo(void)
+{
+ while (1) ;
+}
+#endif
+
+#ifdef TEST1
+void foo(void)
+{
+ while (1) ;
+ x++; /* WARNING(SDCC) */
+}
+#endif
+
+#ifdef TEST2
+void foo(void)
+{
+ int y=1;
+ while (y) ; /* WARNING(SDCC) */
+ x++; /* WARNING(SDCC) */
+}
+#endif
diff --git a/support/valdiag/tests/const.c b/support/valdiag/tests/const.c
new file mode 100644
index 0000000..5082081
--- /dev/null
+++ b/support/valdiag/tests/const.c
@@ -0,0 +1,21 @@
+
+char a;
+const char ca=2;
+const char *pca;
+char * const cpa=&a;
+
+void test(void)
+{
+ a = 1;
+#ifdef TEST1
+ ca = a; /* ERROR */
+#endif
+#ifdef TEST2
+ pca = &a;
+ *pca = 2; /* ERROR */
+#endif
+#ifdef TEST3
+ *cpa = 3;
+ cpa = &ca; /* ERROR */
+#endif
+}
diff --git a/support/valdiag/tests/constantRange.c b/support/valdiag/tests/constantRange.c
new file mode 100644
index 0000000..8e4c793
--- /dev/null
+++ b/support/valdiag/tests/constantRange.c
@@ -0,0 +1,267 @@
+#include <stdint.h>
+
+volatile int8_t c;
+
+/* sorry about the uggly source,
+ but this way it can be the same as in the regression tests */
+#define ASSERT(x) c = (x)
+
+ int8_t s8;
+uint8_t u8;
+
+ int16_t s16;
+uint16_t u16;
+
+ int32_t s32;
+uint32_t u32;
+
+#ifdef TEST1
+void foo(void)
+{
+ ASSERT (! (INT8_MIN - 1 == s8)); /* WARNING */
+ ASSERT (! (INT8_MAX + 1 == s8)); /* WARNING */
+ ASSERT ( (INT8_MIN - 1 != s8)); /* WARNING */
+ ASSERT ( (INT8_MAX + 1 != s8)); /* WARNING */
+ ASSERT ( (INT8_MIN - 1 < s8)); /* WARNING */
+ ASSERT (! (INT8_MAX < s8)); /* WARNING */
+ ASSERT ( (INT8_MIN <= s8)); /* WARNING */
+ ASSERT (! (INT8_MAX + 1 <= s8)); /* WARNING */
+ ASSERT (! (INT8_MIN > s8)); /* WARNING */
+ ASSERT ( (INT8_MAX + 1 > s8)); /* WARNING */
+ ASSERT (! (INT8_MIN - 1 >= s8)); /* WARNING */
+ ASSERT ( (INT8_MAX >= s8)); /* WARNING */
+
+ ASSERT (! ( 0 - 1 == u8)); /* WARNING */
+ ASSERT (! (UINT8_MAX + 1 == u8)); /* WARNING */
+ ASSERT ( ( 0 - 1 != u8)); /* WARNING */
+ ASSERT ( (UINT8_MAX + 1 != u8)); /* WARNING */
+ ASSERT ( ( 0 - 1 < u8)); /* WARNING */
+ ASSERT (! (UINT8_MAX < u8)); /* WARNING */
+ ASSERT ( ( 0 <= u8)); /* WARNING */
+ ASSERT (! (UINT8_MAX + 1 <= u8)); /* WARNING */
+ ASSERT (! ( 0 > u8)); /* WARNING */
+ ASSERT ( (UINT8_MAX + 1 > u8)); /* WARNING */
+ ASSERT (! ( 0 - 1 >= u8)); /* WARNING */
+ ASSERT ( (UINT8_MAX >= u8)); /* WARNING */
+
+ /* force extension to long to avoid int (16 bit) overflow */
+ ASSERT (! (INT16_MIN - 1L == s16)); /* WARNING */
+ ASSERT (! (INT16_MAX + 1L == s16)); /* WARNING */
+ ASSERT ( (INT16_MIN - 1L != s16)); /* WARNING */
+ ASSERT ( (INT16_MAX + 1L != s16)); /* WARNING */
+ ASSERT ( (INT16_MIN - 1L < s16)); /* WARNING */
+ ASSERT (! (INT16_MAX < s16)); /* WARNING */
+ ASSERT ( (INT16_MIN <= s16)); /* WARNING */
+ ASSERT (! (INT16_MAX + 1L <= s16)); /* WARNING */
+ ASSERT (! (INT16_MIN > s16)); /* WARNING */
+ ASSERT ( (INT16_MAX + 1L > s16)); /* WARNING */
+ ASSERT (! (INT16_MIN - 1L >= s16)); /* WARNING */
+ ASSERT ( (INT16_MAX >= s16)); /* WARNING */
+
+ ASSERT (! ( 0 - 1L == u16)); /* WARNING */
+ ASSERT (! (UINT16_MAX + 1L == u16)); /* WARNING */
+ ASSERT ( ( 0 - 1L != u16)); /* WARNING */
+ ASSERT ( (UINT16_MAX + 1L != u16)); /* WARNING */
+ ASSERT ( ( 0 - 1L < u16)); /* WARNING */
+ ASSERT (! (UINT16_MAX < u16)); /* WARNING */
+ ASSERT ( ( 0 <= u16)); /* WARNING */
+ ASSERT (! (UINT16_MAX + 1L <= u16)); /* WARNING */
+ ASSERT (! ( 0 > u16)); /* WARNING */
+ ASSERT ( (UINT16_MAX + 1L > u16)); /* WARNING */
+ ASSERT (! ( 0 - 1L >= u16)); /* WARNING */
+ ASSERT ( (UINT16_MAX >= u16)); /* WARNING */
+
+ /* sdcc can't hold a number (INT32_MIN - 1) or (INT32_MAX + 1),
+ there's no 'double' or 'long long' */
+/* ASSERT (! (INT32_MIN - 1 == s32)); */
+/* ASSERT (! (INT32_MAX + 1 == s32)); */
+/* ASSERT ( (INT32_MIN - 1 != s32)); */
+/* ASSERT ( (INT32_MAX + 1 != s32)); */
+/* ASSERT ( (INT32_MIN - 1 < s32)); */
+ ASSERT (! (INT32_MAX < s32)); /* WARNING(SDCC) */
+ ASSERT ( (INT32_MIN <= s32)); /* WARNING(SDCC) */
+/* ASSERT (! (INT32_MAX + 1 <= s32)); */
+ ASSERT (! (INT32_MIN > s32)); /* WARNING(SDCC) */
+/* ASSERT ( (INT32_MAX + 1 > s32)); */
+/* ASSERT (! (INT32_MIN - 1 >= s32)); */
+ ASSERT ( (INT32_MAX >= s32)); /* WARNING(SDCC) */
+
+ /* (0 - 1) wraps around to UINT32_MAX -> untestable */
+/* ASSERT (! ( 0 - 1 == u32)); */
+/* ASSERT (! (UINT32_MAX + 1 == u32)); */
+/* ASSERT ( ( 0 - 1 != u32)); */
+/* ASSERT ( (UINT32_MAX + 1 != u32)); */
+/* ASSERT ( ( 0 - 1 < u32)); */
+ ASSERT (! (UINT32_MAX < u32)); /* WARNING(SDCC) */
+ ASSERT ( ( 0 <= u32)); /* WARNING(SDCC) */
+/* ASSERT (! (UINT32_MAX + 1 <= u32)); */
+ ASSERT (! ( 0 > u32)); /* WARNING(SDCC) */
+/* ASSERT ( (UINT32_MAX + 1 > u32)); */
+/* ASSERT (! ( 0 - 1 >= u32)); */
+ ASSERT ( (UINT32_MAX >= u32)); /* WARNING(SDCC) */
+}
+#endif
+
+#ifdef TEST2
+void foo(void)
+{
+ s8 = -129; /* WARNING */
+ s8 = INT8_MIN;
+ s8 = UINT8_MAX; /* WARNING */
+ s8 = 256; /* WARNING */
+
+ s8 = -129; /* WARNING */
+ u8 = INT8_MIN; /* WARNING */
+ u8 = UINT8_MAX;
+ u8 = 256; /* WARNING */
+
+ s16 = -32769L; /* WARNING */
+ s16 = INT16_MIN;
+ s16 = UINT16_MAX; /* WARNING */
+ s16 = 65536L; /* WARNING */
+
+ s16 = -32769L; /* WARNING */
+ u16 = INT16_MIN; /* WARNING */
+ u16 = UINT16_MAX;
+ u16 = 65536L; /* WARNING */
+
+ /* sdcc can't hold a number (INT32_MIN - 1) or (INT32_MAX + 1),
+ there's no 'double' or 'long long' */
+ s32 = INT32_MIN;
+ s32 = UINT32_MAX; /* WARNING */
+
+ u32 = INT32_MIN; /* WARNING */
+ u32 = UINT32_MAX;
+}
+#endif
+
+/* This test has been disabled. I don't think that signed/unsigned bool */
+/* is a valid type. -- EEP */
+#ifdef TEST3_DISABLED
+#include <stdbool.h>
+
+void foo(void)
+{
+#if defined(PORT_HOST)
+ volatile bool sb, ub;
+#else
+ volatile signed bool sb;
+ volatile unsigned bool ub;
+#endif
+
+ sb = -2;
+ sb = -1;
+ sb = 0;
+ sb = 1;
+
+ ub = -1;
+ ub = 0;
+ ub = 1;
+ ub = 2;
+
+ ASSERT (! (-2 == sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+ ASSERT ( (-1 == sb));
+ ASSERT ( ( 0 == sb));
+ ASSERT (! ( 1 == sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT ( (-2 != sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+ ASSERT ( (-1 != sb));
+ ASSERT ( ( 0 != sb));
+ ASSERT ( ( 1 != sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT ( (-2 < sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+ ASSERT ( (-1 < sb));
+ ASSERT (! ( 0 < sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT ( (-1 <= sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+ ASSERT ( ( 0 <= sb));
+ ASSERT (! ( 1 <= sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT (! (-1 > sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+ ASSERT ( ( 0 > sb));
+ ASSERT ( ( 1 > sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT (! (-2 >= sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+ ASSERT ( (-1 >= sb));
+ ASSERT ( ( 0 >= sb)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+
+ ASSERT (! (-1 == ub)); /* WARNING(SDCC) */
+ ASSERT ( ( 0 == ub));
+ ASSERT ( ( 1 == ub));
+ ASSERT (! ( 2 == ub)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT ( (-1 != ub)); /* WARNING(SDCC) */
+ ASSERT ( ( 0 != ub));
+ ASSERT ( ( 1 != ub));
+ ASSERT ( ( 2 != ub)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT ( (-1 < ub)); /* WARNING(SDCC) */
+ ASSERT ( ( 0 < ub));
+ ASSERT (! ( 1 < ub)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT ( ( 0 <= ub)); /* WARNING(SDCC) */
+ ASSERT ( ( 1 <= ub));
+ ASSERT (! ( 2 <= ub)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT (! ( 0 > ub)); /* WARNING(SDCC) */
+ ASSERT ( ( 1 > ub));
+ ASSERT ( ( 2 > ub)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+
+ ASSERT (! (-1 >= ub)); /* WARNING(SDCC) */
+ ASSERT ( ( 0 >= ub));
+ ASSERT ( ( 1 >= ub)); /* WARNING(SDCC_mcs51|SDCC_ds390) */
+}
+#endif
+
+#ifdef TEST4
+void foo(void)
+{
+ volatile struct {
+ signed sb1:1;
+ signed sb3:3;
+ unsigned ub1:1;
+ unsigned ub3:3;
+ } str;
+
+ str.sb1 = -2; /* WARNING */
+ str.sb1 = -1;
+ str.sb1 = 1; /* WARNING */
+ str.sb1 = 2; /* WARNING */
+
+ str.ub1 = -2; /* WARNING */
+ str.ub1 = -1; /* WARNING */
+ str.ub1 = 1;
+ str.ub1 = 2; /* WARNING */
+
+ str.sb3 = -5; /* WARNING */
+ str.sb3 = -4;
+ str.sb3 = 7; /* WARNING */
+ str.sb3 = 8; /* WARNING */
+
+ str.ub3 = -5; /* WARNING */
+ str.ub3 = -4; /* WARNING */
+ str.ub3 = 7;
+ str.ub3 = 8; /* WARNING */
+
+ ASSERT (! (-2 == str.sb1)); /* WARNING */
+ ASSERT ( (-1 == str.sb1));
+ ASSERT ( ( 0 == str.sb1));
+ ASSERT (! ( 1 == str.sb1)); /* WARNING */
+
+ ASSERT (! (-1 == str.ub1)); /* WARNING(SDCC) */
+ ASSERT ( ( 0 == str.ub1));
+ ASSERT ( ( 1 == str.ub1));
+ ASSERT (! ( 2 == str.ub1)); /* WARNING(SDCC) */
+
+ ASSERT (! (-5 == str.sb3)); /* WARNING */
+ ASSERT ( (-4 == str.sb3));
+ ASSERT ( ( 3 == str.sb3));
+ ASSERT (! ( 4 == str.sb3)); /* WARNING */
+
+ ASSERT (! (-1 == str.ub3)); /* WARNING(SDCC) */
+ ASSERT ( ( 0 == str.ub3));
+ ASSERT ( ( 7 == str.ub3));
+ ASSERT (! ( 8 == str.ub3)); /* WARNING(SDCC) */
+}
+#endif
diff --git a/support/valdiag/tests/declafterstmt.c b/support/valdiag/tests/declafterstmt.c
new file mode 100644
index 0000000..51ce7ca
--- /dev/null
+++ b/support/valdiag/tests/declafterstmt.c
@@ -0,0 +1,45 @@
+/* we are testing a C99 feature */
+#pragma std_c99
+
+/* we do not care about unreferenced variables */
+#pragma disable_warning 85
+
+#ifdef TEST1
+#pragma std_c89
+void test(void)
+{
+ int a = 0;
+ a++;
+ int b;
+} /* ERROR */ /* declaration after statement within this block */
+#endif
+
+#ifdef TEST2
+void test(void)
+{
+ int a = 0;
+ a++;
+ int b;
+}
+#endif
+
+#ifdef TEST3
+void test(void)
+{
+ int a = 0; /* ERROR */ /* previously defined here */
+ a++;
+ int a; /* ERROR */ /* duplicate symbol */
+}
+#endif
+
+#ifdef TEST4
+void test(void)
+{
+ int a = 0;
+ a++;
+ int b;
+ {
+ int a;
+ }
+}
+#endif
diff --git a/support/valdiag/tests/enum.c b/support/valdiag/tests/enum.c
new file mode 100644
index 0000000..ac50ca1
--- /dev/null
+++ b/support/valdiag/tests/enum.c
@@ -0,0 +1,89 @@
+
+#ifdef TEST1
+enum tag
+{
+ first,
+ second,
+ third
+};
+#endif
+
+#ifdef TEST2
+enum tag
+{
+ first, /* IGNORE */
+ second,
+ third,
+ first, /* ERROR */
+ fourth
+};
+#endif
+
+
+#ifdef TEST3
+enum
+{
+ first, /* IGNORE */
+ second,
+ third,
+ first, /* ERROR */
+ fourth
+};
+#endif
+
+
+#ifdef TEST4
+enum
+{
+ first=1,
+ second,
+ third,
+};
+#endif
+
+
+#ifdef TEST5
+enum
+{
+ first=1.1, /* ERROR */
+ second,
+ third,
+};
+#endif
+
+#ifdef TEST6
+int second; /* IGNORE */
+
+enum tag
+{
+ first,
+ second, /* ERROR */
+ third
+};
+#endif
+
+#ifdef TEST7
+enum tag /* IGNORE */
+{
+ first,
+ second,
+ third
+};
+
+enum tag { /* ERROR */
+ fourth,
+ fifth,
+ sixth
+};
+#endif
+
+#ifdef TEST8
+enum tag x; /* IGNORE(GCC) */
+
+enum tag
+{
+ first,
+ second,
+ third
+};
+#endif
diff --git a/support/valdiag/tests/funcdec.c b/support/valdiag/tests/funcdec.c
new file mode 100644
index 0000000..c2e10bb
--- /dev/null
+++ b/support/valdiag/tests/funcdec.c
@@ -0,0 +1,48 @@
+
+#ifdef TEST1
+void foo(void); /* IGNORE */
+int foo(void) { } /* ERROR */
+#endif
+
+#ifdef TEST2
+void foo(void); /* IGNORE */
+void foo(int a) {a; } /* ERROR */
+#endif
+
+
+#ifdef TEST3
+void foo(int); /* IGNORE */
+void foo(int a, int b) {a;b; } /* ERROR */
+#endif
+
+#ifdef TEST4
+void foo(int, int); /* IGNORE */
+void foo(int a) {a; } /* ERROR */
+#endif
+
+#if defined(__SDCC) && defined(__has_reentrant)
+#define REENTRANT __reentrant
+#define HAS_REENTRANT 1
+#else
+#define REENTRANT
+#define HAS_REENTRANT 0
+#endif
+
+#ifdef TEST5
+void foo(int, int) REENTRANT; /* IGNORE */
+#if HAS_REENTRANT
+void foo(int a, int b) {a; b;} /* ERROR(SDCC && __has_reentrant && !SDCC_STACK_AUTO) */
+#endif
+#endif
+
+#ifdef TEST6
+void foo(int a=1) /* ERROR */
+{
+}
+#endif
+
+#ifdef TEST7
+void foo(static int a) /* ERROR */
+{
+}
+#endif
diff --git a/support/valdiag/tests/overflow.c b/support/valdiag/tests/overflow.c
new file mode 100644
index 0000000..39ecbd3
--- /dev/null
+++ b/support/valdiag/tests/overflow.c
@@ -0,0 +1,61 @@
+volatile char c;
+volatile unsigned char uc;
+volatile int i;
+volatile unsigned u;
+volatile long l;
+volatile unsigned long ul;
+
+#ifdef TEST0
+void foo(void)
+{
+ i = 10000 * 10000; /* WARNING(SDCC) */
+ i = 0x4000 * 0x4000; /* WARNING(SDCC) */
+}
+#endif
+
+#ifdef TEST1
+void foo(void)
+{
+ uc = 1 << 7; /* IGNORE(SDCC) */ // Gives a false warning (bug #2733)
+
+ i = c << 10;
+ i = 1 << 10;
+ i = c << 16; /* WARNING(SDCC) */
+ i = 1 << 16; /* WARNING(SDCC) */
+ i = uc << 16; /* WARNING(SDCC) */
+
+ l = l << 31;
+ l = l << 32; /* WARNING(SDCC) */ /* IGNORE(GCC) */
+ l = ul << 32; /* WARNING(SDCC) */ /* IGNORE(GCC) */
+}
+#endif
+
+
+#ifdef TEST2
+void foo(void)
+{
+ i = 1 >> 40; /* IGNORE(SDCC) */ /* WARNING(GCC) */ // Warning missing (bug #2734)
+
+ i = uc >> 7;
+ i = 1 >> 7;
+ i = uc >> 8; /* WARNING(SDCC) */
+#if 0
+ i = 1 >> 8; /* WARN___(SDCC) */
+#endif
+
+#if 0
+ i = i >> 40; /* WARN___(GCC) */
+#endif
+
+ i = u >> 15;
+ i = u >> 16; /* WARNING(SDCC) */
+
+#if 0
+ i = l >> 40; /* WARN___(GCC) */
+#endif
+
+ i = ul >> 31;
+ i = ul >> 32; /* WARNING(SDCC) */ /* IGNORE(GCC) */
+}
+#endif
+
diff --git a/support/valdiag/tests/pointers.c b/support/valdiag/tests/pointers.c
new file mode 100644
index 0000000..16d71b1
--- /dev/null
+++ b/support/valdiag/tests/pointers.c
@@ -0,0 +1,21 @@
+
+#ifdef TEST0
+
+typedef void (*fptr1_t)(void);
+typedef void (*fptr2_t)(int);
+
+fptr1_t fptr1;
+fptr2_t fptr2;
+
+void *vp = 0;
+
+void testPtr(void)
+{
+ fptr1 = vp; /* WARNING */
+ fptr2 = fptr1; /* IGNORE(GCC) */
+ vp = fptr1; /* WARNING */
+ fptr1 = (void *)0;
+}
+
+#endif
+
diff --git a/support/valdiag/tests/primtypes.c b/support/valdiag/tests/primtypes.c
new file mode 100644
index 0000000..c6dac5c
--- /dev/null
+++ b/support/valdiag/tests/primtypes.c
@@ -0,0 +1,100 @@
+#ifdef TESTchar
+char a;
+#endif
+
+#ifdef TESTint
+int a;
+#endif
+
+#ifdef TESTlong
+long a;
+#endif
+
+#ifdef TESTshort
+short a;
+#endif
+
+#ifdef TESTintlong
+long int a;
+#endif
+
+#ifdef TESTintshort
+short int a;
+#endif
+
+#ifdef TESTsigned
+signed a;
+#endif
+
+#ifdef TESTunsigned
+unsigned a;
+#endif
+
+#ifdef TESTintsigned
+signed int a;
+#endif
+
+#ifdef TESTintunsigned
+unsigned int a;
+#endif
+
+#ifdef TESTfloat
+float a;
+#endif
+
+#ifdef TESTfloatsigned
+signed float a; /* ERROR */
+#endif
+
+#ifdef TESTfloatunsigned
+unsigned float a; /* ERROR */
+#endif
+
+#ifdef TESTfloatshort
+short float a; /* ERROR */
+#endif
+
+#ifdef TESTfloatlong
+long float a; /* ERROR */
+#endif
+
+#ifdef TESTdouble
+double a; /* WARNING(SDCC) */
+#endif
+
+#ifdef TESTdoubleshort
+short double a; /* ERROR */
+#endif
+
+#ifdef TESTdoublelong
+long double a; /* WARNING(SDCC) */
+#endif
+
+#ifdef TESTdoublesigned
+signed double a; /* ERROR */
+#endif
+
+#ifdef TESTdoubleunsigned
+unsigned double a; /* ERROR */
+#endif
+
+#ifdef TESTbit
+__bit a; /* ERROR(!__has_bit) */
+#endif
+
+#ifdef TESTsu1
+signed unsigned int a; /* ERROR */
+#endif
+
+#ifdef TESTsu2
+unsigned signed int a; /* ERROR */
+#endif
+
+#ifdef TESTsu3
+unsigned signed a; /* ERROR */
+#endif
+
+#ifdef TESTsu4
+signed unsigned a; /* ERROR */
+#endif
+
diff --git a/support/valdiag/tests/restrict.c b/support/valdiag/tests/restrict.c
new file mode 100644
index 0000000..3dbcee3
--- /dev/null
+++ b/support/valdiag/tests/restrict.c
@@ -0,0 +1,63 @@
+
+/* The restrict keyword can only qualify pointers to objects */
+
+#ifdef TEST1_C99
+restrict a; /* ERROR */
+#endif
+
+#ifdef TEST2_C99
+restrict int a; /* ERROR */
+#endif
+
+#ifdef TEST3_C99
+restrict int a[10]; /* ERROR */
+#endif
+
+#ifdef TEST4_C99
+restrict int * a; /* ERROR */
+#endif
+
+#ifdef TEST5_C99
+restrict struct
+ {
+ int a;
+ int b;
+ } x; /* ERROR */
+#endif
+
+#ifdef TEST6_C99
+restrict int func(void) { /* ERROR */
+ return 0;
+}
+#endif
+
+#ifdef TEST7_C99
+void func(restrict int x) { /* ERROR */
+ x; /* IGNORE */
+}
+#endif
+
+#ifdef TEST8_C99
+void func(void (*restrict p)(void)) { /* ERROR */
+ p(); /* IGNORE */
+}
+#endif
+
+
+#ifdef TEST_GOOD1_C99
+int * restrict a;
+#endif
+
+#ifdef TEST_GOOD2_C99
+int * func(int * restrict x)
+{
+ return x;
+}
+#endif
+
+#ifdef TEST_GOOD3_C99
+void func(int * restrict x)
+{
+ x; /* IGNORE */
+}
+#endif
diff --git a/support/valdiag/tests/static_assert.c b/support/valdiag/tests/static_assert.c
new file mode 100644
index 0000000..c4a6254
--- /dev/null
+++ b/support/valdiag/tests/static_assert.c
@@ -0,0 +1,19 @@
+#pragma std_c11
+
+#include <assert.h>
+
+/* C11 static_assert */
+#ifdef TEST1
+#pragma std_c11
+static_assert (1, "text");
+static_assert (0, "test"); /* WARNING */
+static_assert (1); /* ERROR */
+#endif
+
+/* C2X static_assert */
+#ifdef TEST2
+#pragma std_c2x
+static_assert (1);
+static_assert (0); /* WARNING */
+#endif
+
diff --git a/support/valdiag/tests/struct.c b/support/valdiag/tests/struct.c
new file mode 100644
index 0000000..c7f4938
--- /dev/null
+++ b/support/valdiag/tests/struct.c
@@ -0,0 +1,115 @@
+
+#ifdef TEST1
+struct tag {
+ int good1;
+ register int bad; /* ERROR */
+ int good2;
+} badstruct; /* IGNORE */
+#endif
+
+#ifdef TEST2
+struct tag {
+ int good1;
+ int bad; /* IGNORE */
+ int bad; /* ERROR */
+ int good2;
+} badstruct;
+#endif
+
+#ifdef TEST3a
+struct tag {
+ int good1;
+ int bad:255; /* ERROR */
+ int good2;
+} badstruct;
+#endif
+
+#ifdef TEST3b
+struct tag {
+ int good1;
+ float badtype1 : 5; /* ERROR */
+ int good2;
+ _Bool badwidth2 : 2; /* ERROR */
+ int good3;
+ int badwidth2 : 17; /* ERROR */
+ int good4;
+} badstruct;
+#endif
+
+#ifdef TEST4
+struct tag {
+ int good1;
+ int good2;
+} goodstruct1;
+
+struct tag goodstruct2;
+#endif
+
+#ifdef TEST5a
+struct tag {
+ int good1;
+ int good2;
+} goodstruct1;
+
+union tag badunion; /* ERROR */
+#endif
+
+#ifdef TEST5b
+union tag {
+ int good1;
+ int good2;
+} goodunion1;
+
+struct tag badstruct; /* ERROR */
+#endif
+
+
+#ifdef TEST6
+struct linklist {
+ struct linklist *prev;
+ struct linklist *next;
+ int x;
+} ll;
+#endif
+
+#ifdef TEST7a
+union tag {
+ struct tag *next; /* ERROR */
+ int x;
+} ll;
+#endif
+
+#ifdef TEST7b
+struct tag {
+ union tag *next; /* ERROR */
+ int x;
+} ll;
+#endif
+
+#ifdef TEST8a
+struct tag {
+ int a; /* IGNORE */
+ struct {
+ int a; /* ERROR(SDCC) */ /* IGNORE(GCC) */
+ int b;
+ };
+} ll;
+#endif
+
+#ifdef TEST8b
+struct tag {
+ int a;
+ struct {
+ int b;
+ int c;
+ };
+} ll;
+
+void test(void)
+{
+ ll.a = 1;
+ ll.b = 2;
+ ll.c = 3;
+}
+
+#endif
diff --git a/support/valdiag/tests/structflexiblearray.c b/support/valdiag/tests/structflexiblearray.c
new file mode 100644
index 0000000..9f1c8e3
--- /dev/null
+++ b/support/valdiag/tests/structflexiblearray.c
@@ -0,0 +1,24 @@
+
+#ifdef TEST1
+struct tag {
+ int good1;
+ int flex[]; /* ERROR */
+ int good2;
+} badstruct;
+#endif
+
+#ifdef TEST2
+struct tag {
+ int flex[]; /* ERROR */
+} badstruct;
+#endif
+
+#ifdef TEST3
+struct tag {
+ int good1;
+ struct tag2 {
+ int good2;
+ int flex[];
+ } nestedstruct; /* ERROR(SDCC) */
+} badstruct;
+#endif
diff --git a/support/valdiag/tests/switch.c b/support/valdiag/tests/switch.c
new file mode 100644
index 0000000..b9acd42
--- /dev/null
+++ b/support/valdiag/tests/switch.c
@@ -0,0 +1,158 @@
+
+char x;
+
+/* Valid switch statement */
+#ifdef TEST1
+char foo(void)
+{
+ switch(x)
+ {
+ char y;
+
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ default:
+ y = x+1;
+ return y;
+ }
+}
+#endif
+
+/* Error, duplicate cases */
+#ifdef TEST2
+char foo(void)
+{
+ switch(x)
+ {
+ char y;
+
+ case 0: /* IGNORE */
+ return 0;
+ case 1:
+ return 1;
+ case 0: /* ERROR */
+ return 0;
+ default:
+ y = x;
+ return y;
+ }
+}
+#endif
+
+/* Error, more than one default */
+#ifdef TEST3
+char foo(void)
+{
+ switch(x)
+ {
+ char y;
+
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ default: /* IGNORE */
+ y = x;
+ return y;
+ default: /* ERROR */
+ return 2;
+ }
+}
+#endif
+
+/* Warn about unreachable code */
+#ifdef TEST4
+char foo(void)
+{
+ switch(x)
+ {
+ char y; /* IGNORE */
+ x++; /* WARNING(SDCC) */
+
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ default:
+ y = x;
+ return x;
+ }
+}
+#endif
+
+/* Warn about unreachable initializer */
+#ifdef TEST5
+char foo(void)
+{
+ switch(x)
+ {
+ char y=1; /* WARNING(SDCC) */
+
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ default:
+ return y; /* IGNORE */
+ }
+}
+#endif
+
+/* Error, missing switch */
+#ifdef TEST6
+char foo(void)
+{
+ {
+ case 0: /* ERROR */
+ return 0;
+ case 1: /* ERROR */
+ return 1;
+ default: /* ERROR */
+ return x;
+ }
+}
+#endif
+
+/* Error, switch condition must be integral */
+#ifdef TEST7
+char foo(void)
+{
+ float f; /* IGNORE */
+ f=x;
+ switch(f) /* ERROR */
+ {
+ char y; /* IGNORE */
+
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ default:
+ y = x;
+ return x;
+ }
+ return 0;
+}
+#endif
+
+/* Error, cases must be integral */
+#ifdef TEST8
+char foo(void)
+{
+ switch(x)
+ {
+ char y; /* IGNORE */
+
+ case 0.0: /* ERROR */
+ return 0;
+ case 1:
+ return 1;
+ default:
+ y = x;
+ return x;
+ }
+}
+#endif
+
diff --git a/support/valdiag/tests/tentdecl.c b/support/valdiag/tests/tentdecl.c
new file mode 100644
index 0000000..8b8e6b7
--- /dev/null
+++ b/support/valdiag/tests/tentdecl.c
@@ -0,0 +1,127 @@
+
+#ifdef TEST0
+int a;
+int a;
+#endif
+
+#ifdef TEST1
+int a; /* IGNORE */
+char a; /* ERROR */
+#endif
+
+#ifdef TEST2
+int a; /* IGNORE */
+int *a; /* ERROR */
+#endif
+
+#ifdef TEST3
+int *a; /* IGNORE */
+int a[5]; /* ERROR */
+#endif
+
+/* array size must match */
+
+#ifdef TEST4
+int a[4]; /* IGNORE */
+int a[5]; /* ERROR */
+#endif
+
+/* but it is legal to clarify */
+/* an incomplete type */
+
+#ifdef TEST4b
+int a[];
+int a[5];
+#endif
+
+/* type qualifier must match */
+
+#ifdef TEST5
+int a; /* IGNORE */
+volatile int a; /* ERROR */
+#endif
+
+#ifdef TEST6
+int a; /* IGNORE */
+const int a; /* ERROR */
+#endif
+
+#ifdef TEST7
+int a=1; /* IGNORE */
+int a=2; /* ERROR */
+#endif
+
+#ifdef TEST7a
+int a=1;
+int a;
+#endif
+
+#ifdef TEST8
+int a=1; /* IGNORE */
+int a=1; /* ERROR */
+#endif
+
+#if defined(__SDCC)
+#define AT(x) __at x
+#else
+#define AT(x)
+#endif
+
+#if defined(__has_xdata)
+#define XDATA __xdata
+#define DATA __data
+#else
+#define XDATA
+#define DATA
+#endif
+
+#ifdef TEST9
+#ifdef __SDCC
+XDATA int a; /* IGNORE */
+DATA int a; /* IGNORE(SDCC && __has_xdata) */ // Should be error, see bug #2735.
+#endif
+#endif
+
+#ifdef TEST9b
+#ifdef __SDCC
+DATA int a; /* IGNORE */
+XDATA int a; /* ERROR(SDCC && __has_xdata) */
+#endif
+#endif
+
+#ifdef TEST9c
+#ifdef __SDCC
+extern DATA int a;
+DATA int a;
+#endif
+#endif
+
+#ifdef TEST9d
+#ifdef __SDCC
+extern XDATA int a;
+XDATA int a;
+#endif
+#endif
+
+#ifdef TEST9e
+#ifdef __SDCC
+extern XDATA int a; /* IGNORE */
+DATA int a; /* ERROR(SDCC && __has_xdata) */
+#endif
+#endif
+
+#ifdef TEST9f
+#ifdef __SDCC
+extern DATA int a; /* IGNORE */
+XDATA int a; /* ERROR(SDCC && __has_xdata) */
+#endif
+#endif
+
+#ifdef TEST10
+#if defined(__SDCC) && defined(__has_xdata)
+extern volatile XDATA AT(0) int a; /* IGNORE */
+volatile XDATA int a; /* ERROR(SDCC && __has_xdata) */
+#endif
+#endif
+
+int validDeclaraction; /* to make sure this is never an empty source file */
diff --git a/support/valdiag/tests/typedef.c b/support/valdiag/tests/typedef.c
new file mode 100644
index 0000000..a24cbcc
--- /dev/null
+++ b/support/valdiag/tests/typedef.c
@@ -0,0 +1,45 @@
+
+#ifdef TEST1
+typedef union {
+ long l;
+ float f;
+} floatlong;
+
+char func(char floatlong)
+{
+ return floatlong;
+}
+#endif
+
+#ifdef TEST2
+typedef union {
+ long l;
+ float f;
+} floatlong;
+
+long func(float x)
+{
+ typedef union {
+ float f2;
+ long l2;
+ char c[4];
+ } floatlong;
+ floatlong fl;
+
+ fl.f2=x;
+ return fl.l2;
+}
+#endif
+
+/* This is no longer an error in C11, so test with earlier standard. */
+/* Unfortunately, GCC seems to accept this regardless. */
+#ifdef TEST3_C99
+typedef int I; /* IGNORE */
+typedef int I; /* ERROR(SDCC) */
+#endif
+
+#ifdef TEST4
+typedef int I; /* IGNORE */
+typedef char I; /* ERROR */
+#endif
+
diff --git a/support/valdiag/valdiag.py b/support/valdiag/valdiag.py
new file mode 100644
index 0000000..469b5c1
--- /dev/null
+++ b/support/valdiag/valdiag.py
@@ -0,0 +1,397 @@
+#!/usr/bin/env python
+#---------------------------------------------------------------------------
+# valdiag.py - Validate diagnostic messages from SDCC/GCC
+# Written By - Erik Petrich . epetrich@users.sourceforge.net (2003)
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# In other words, you are welcome to use, share and improve this program.
+# You are forbidden to forbid anyone else to use, share and improve
+# what you give them. Help stamp out software-hoarding!
+#---------------------------------------------------------------------------
+
+from __future__ import print_function
+
+import sys, string, os, re, subprocess
+from subprocess import Popen, PIPE, STDOUT
+
+macrodefs = {}
+extramacrodefs = {}
+
+gcc = {
+ "CC":"gcc",
+ "CCFLAGS":"-c -pedantic -Wall -DPORT_HOST=1",
+ "CCDEF":"-D",
+ "CCOUTPUT":"-o",
+ "C89":"-std=c89",
+ "C99":"-std=c99",
+ "defined": {
+ "__GNUC__":"1",
+ "GCC":"1"
+ },
+ "ignoremsg": [
+ ]
+}
+
+sdcc = {
+ "CC":"../../bin/sdcc",
+ "CCFLAGS":"-c -m{port}",
+ "CCDEF":"-D",
+ "CCOUTPUT":"-o",
+ "CCINCLUDEDIR":"-I",
+ "C89":"--std-sdcc89",
+ "C99":"--std-sdcc99",
+ "defined": {
+ "SDCC":"1",
+ "SDCC_{port}":"1",
+ "__{port}":"1"
+ },
+ "ignoremsg": [
+ "code not generated.*due to previous errors",
+ "unreferenced function argument"
+ ]
+}
+
+testmodes = {
+ "host":{
+ "compiler":gcc,
+ "port":"host",
+ "defined": {
+ "PORT_HOST":"1"
+ }
+ },
+ "mcs51":{
+ "compiler":sdcc,
+ "port":"mcs51",
+ "extra-defines": {
+ "__has_bit":"1",
+ "__has_data":"1",
+ "__has_xdata":"1",
+ "__has_reentrant":"1"
+ }
+ },
+ "mcs51-large":{
+ "compiler":sdcc,
+ "port":"mcs51",
+ "flags":"--model-large",
+ "defined": {
+ "SDCC_MODEL_LARGE":"1"
+ },
+ "extra-defines" : {
+ "__has_bit":"1",
+ "__has_data":"1",
+ "__has_xdata":"1",
+ "__has_reentrant":"1"
+ }
+ },
+ "mcs51-stack-auto":{
+ "compiler":sdcc,
+ "port":"mcs51",
+ "flags":"--stack-auto",
+ "defined": {
+ "SDCC_STACK_AUTO":"1"
+ },
+ "extra-defines": {
+ "__has_bit":"1",
+ "__has_data":"1",
+ "__has_xdata":"1",
+ "__has_reentrant":"1"
+ }
+ },
+ "ds390":{
+ "compiler":sdcc,
+ "port":"ds390",
+ "extra-defines": {
+ "__has_bit":"1",
+ "__has_data":"1",
+ "__has_xdata":"1",
+ "__has_reentrant":"1"
+ }
+ },
+ "z80":{
+ "compiler":sdcc,
+ "port":"z80"
+ },
+ "z180":{
+ "compiler":sdcc,
+ "port":"z180"
+ },
+ "r2k":{
+ "compiler":sdcc,
+ "port":"r2k"
+ },
+ "gbz80":{
+ "compiler":sdcc,
+ "port":"gbz80"
+ },
+ "tlcs90":{
+ "compiler":sdcc,
+ "port":"tlcs90"
+ },
+ "hc08":{
+ "compiler":sdcc,
+ "port":"hc08",
+ "extra-defines": {
+ "__has_data":"1",
+ "__has_xdata":"1",
+ "__has_reentrant":"1"
+ }
+ },
+ "s08":{
+ "compiler":sdcc,
+ "port":"s08",
+ "extra-defines": {
+ "__has_data":"1",
+ "__has_xdata":"1",
+ "__has_reentrant":"1"
+ }
+ },
+ "stm8":{
+ "compiler":sdcc,
+ "port":"stm8"
+ },
+ "pdk14":{
+ "compiler":sdcc,
+ "port":"pdk14"
+ },
+ "pic14":{
+ "compiler":sdcc,
+ "port":"pic14"
+ },
+ "pic16":{
+ "compiler":sdcc,
+ "port":"pic16"
+ }
+}
+
+
+def evalQualifier(expr):
+ global macrodefs
+ tokens = re.split("([^0-9A-Za-z_])", expr)
+ for tokenindex in range(len(tokens)):
+ token = tokens[tokenindex]
+ if token in macrodefs:
+ tokens[tokenindex] = macrodefs[token]
+ elif token == "defined":
+ tokens[tokenindex] = ""
+ if tokens[tokenindex+2] in macrodefs:
+ tokens[tokenindex+2] = "1"
+ else:
+ tokens[tokenindex+2] = "0"
+ elif len(token)>0:
+ if token[0]=="_" or token[0] in string.ascii_letters:
+ tokens[tokenindex] = "0"
+ #expr = string.join(tokens,"")
+ expr = "".join(tokens)
+ expr = expr.replace("&&"," and ");
+ expr = expr.replace("||"," or ");
+ expr = expr.replace("!"," not ");
+ return eval(expr)
+
+def expandPyExpr(expr):
+ tokens = re.split("({|})", expr)
+ for tokenindex in range(1,len(tokens)):
+ if tokens[tokenindex-1]=="{":
+ tokens[tokenindex]=eval(tokens[tokenindex])
+ tokens[tokenindex-1]=""
+ tokens[tokenindex+1]=""
+ expandedExpr = "".join(tokens)
+ return expandedExpr
+
+def addDefines(deflist, isExtra):
+ for define in list(deflist.keys()):
+ expandeddef = expandPyExpr(define)
+ macrodefs[expandeddef] = expandPyExpr(deflist[define])
+ if isExtra:
+ extramacrodefs[expandeddef] = macrodefs[expandeddef]
+
+def parseInputfile(inputfilename):
+ inputfile = open(inputfilename, "r")
+ testcases = {}
+ testname = ""
+ linenumber = 1
+
+ # Find the test cases and tests in this file
+ for line in inputfile.readlines():
+
+ # See if a new testcase is being defined
+ p = line.find("TEST")
+ if p>=0:
+ testname = line[p:].split()[0]
+ if testname not in testcases:
+ testcases[testname] = {}
+
+ # See if a new test is being defined
+ for testtype in ["ERROR", "WARNING", "IGNORE"]:
+ p = line.find(testtype);
+ if p>=0:
+ # Found a test definition
+ qualifier = line[p+len(testtype):].strip()
+ p = qualifier.find("*/")
+ if p>=0:
+ qualifier = qualifier[:p].strip()
+ if len(qualifier)==0:
+ qualifier="1"
+ qualifier = evalQualifier(qualifier)
+ if qualifier:
+ if not linenumber in testcases[testname]:
+ testcases[testname][linenumber]=[]
+ testcases[testname][linenumber].append(testtype)
+
+ linenumber = linenumber + 1
+
+ inputfile.close()
+ return testcases
+
+def parseResults(output):
+ results = {}
+ for line in output:
+ print(line, end=' ')
+
+ if line.count("SIGSEG"):
+ results[0] = ["FAULT", line.strip()]
+ continue
+
+ # look for something of the form:
+ # filename:line:message
+ msg = line.split(":",2)
+ if len(msg)<3: continue
+ if msg[0]!=inputfilename: continue
+ if len(msg[1])==0: continue
+ if not msg[1][0] in string.digits: continue
+
+ # it's in the right form; parse it
+ linenumber = int(msg[1])
+ msgtype = "UNKNOWN"
+ uppermsg = msg[2].upper()
+ if uppermsg.count("ERROR"):
+ msgtype = "ERROR"
+ if uppermsg.count("WARNING"):
+ msgtype = "WARNING"
+ msgtext = msg[2].strip()
+ ignore = 0
+ for ignoreExpr in ignoreExprList:
+ if re.search(ignoreExpr,msgtext)!=None:
+ ignore = 1
+ if not ignore:
+ results[linenumber]=[msgtype,msg[2].strip()]
+ return results
+
+def showUsage():
+ print("Usage: test testmode cfile [objectfile]")
+ print("Choices for testmode are:")
+ for testmodename in list(testmodes.keys()):
+ print(" %s" % testmodename)
+ sys.exit(1)
+
+# Start here
+if len(sys.argv)<3:
+ showUsage()
+
+testmodename = sys.argv[1]
+if not testmodename in testmodes:
+ print("Unknown test mode '%s'" % testmodename)
+ showUsage()
+
+testmode = testmodes[testmodename]
+compilermode = testmode["compiler"]
+port = expandPyExpr(testmode["port"])
+cc = expandPyExpr(compilermode["CC"])
+ccflags = expandPyExpr(compilermode["CCFLAGS"])
+if "flags" in testmode:
+ ccflags = " ".join([ccflags,expandPyExpr(testmode["flags"])])
+if len(sys.argv)>=4:
+ if "CCOUTPUT" in compilermode:
+ ccflags = " ".join([ccflags,expandPyExpr(compilermode["CCOUTPUT"]),sys.argv[3]])
+if len(sys.argv)>=5:
+ if "CCINCLUDEDIR" in compilermode:
+ ccflags = " ".join([ccflags,expandPyExpr(compilermode["CCINCLUDEDIR"]),sys.argv[4]])
+if "defined" in compilermode:
+ addDefines(compilermode["defined"], False)
+if "defined" in testmode:
+ addDefines(testmode["defined"], False)
+if "extra-defines" in compilermode:
+ addDefines(compilermode["extra-defines"], True)
+if "extra-defines" in testmode:
+ addDefines(testmode["extra-defines"], True)
+if "ignoremsg" in compilermode:
+ ignoreExprList = compilermode["ignoremsg"]
+else:
+ ignoreExprList = []
+
+inputfilename = sys.argv[2]
+inputfilenameshort = os.path.basename(inputfilename)
+
+try:
+ testcases = parseInputfile(inputfilename)
+except IOError:
+ print("Unable to read file '%s'" % inputfilename)
+ sys.exit(1)
+
+casecount = len(list(testcases.keys()))
+testcount = 0
+failurecount = 0
+
+print("--- Running: %s " % inputfilenameshort)
+for testname in list(testcases.keys()):
+ if testname.find("DISABLED")>=0:
+ continue
+ ccdef = compilermode["CCDEF"]+testname
+ for extradef in list(extramacrodefs.keys()):
+ ccdef = ccdef + " " + compilermode["CCDEF"] + extradef + "=" + extramacrodefs[extradef]
+ if testname[-3:] == "C89":
+ ccstd = compilermode["C89"]
+ elif testname[-3:] == "C99":
+ ccstd = compilermode["C99"]
+ else:
+ ccstd = ""
+ cmd = " ".join([cc,ccflags,ccstd,ccdef,inputfilename])
+ print()
+ print(cmd)
+ spawn = Popen(args=cmd.split(), bufsize=-1, stdout = PIPE, stderr = STDOUT, close_fds=True)
+ (stdoutdata,stderrdata) = spawn.communicate()
+ if not isinstance(stdoutdata, str): # python 3 returns bytes so
+ stdoutdata = str(stdoutdata,"utf-8") # convert to str type first
+ output = stdoutdata.splitlines(True)
+
+ results = parseResults(output)
+
+ if len(testcases[testname])==0:
+ testcount = testcount + 1 #implicit test for no errors
+
+ # Go through the tests of this case and make sure
+ # the compiler gave a diagnostic
+ for checkline in list(testcases[testname].keys()):
+ testcount = testcount + 1
+ if checkline in results:
+ if "IGNORE" in testcases[testname][checkline]:
+ testcount = testcount - 1 #this isn't really a test
+ del results[checkline]
+ else:
+ for wanted in testcases[testname][checkline]:
+ if not wanted=="IGNORE":
+ print("--- FAIL: expected %s" % wanted, end=' ')
+ print("at %s:%d" % (inputfilename, checkline))
+ failurecount = failurecount + 1
+
+ # Output any unexpected diagnostics
+ for checkline in list(results.keys()):
+ print('--- FAIL: unexpected message "%s" ' % results[checkline][1], end=' ')
+ print("at %s:%d" % (inputfilename, checkline))
+ failurecount = failurecount + 1
+
+print()
+print("--- Summary: %d/%d/%d: " % (failurecount, testcount, casecount), end=' ')
+print("%d failed of %d tests in %d cases." % (failurecount, testcount, casecount))