1 /** bug2729218.c
2 */
3 
4 #include <testfwk.h>
5 
6 /*
7 
8 sdcc appears to compile the following file incorrectly.  I have attached
9 the C source code, and the generated assembly code, with some comments
10 that explain the bug.
11 
12 The basic problem is that a memory location is post-incremented, but
13 the register variable that shadows that memory location is NOT
14 increment, and this incorrect value is used in later calculations.
15 
16 I compiled it with these options:
17 
18     sdcc -mmcs51 --model-small --std-sdcc99 --code-loc 0xf000 -c bug.c
19 
20 Here is the "sdcc -v" output:
21 
22     SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.9.1 #5422 (Apr  3 2009) (UNIX)
23 
24 */
25 
26 struct iglobals
27 {
28   unsigned char rx_byte;
29   unsigned char input_cnt;
30 };
31 
32 #if !defined(__SDCC_gbz80) && !defined(__SDCC_pdk14)
33 #define ig (*(__idata struct iglobals *) 0xf0)
34 #else
35 struct iglobals ig;
36 #endif
37 
38 unsigned char count;
39 
40 unsigned char
do_command(void)41 do_command(void)
42 {
43   // In the following statement, the post-increment is saved in
44   // memory, but not in the value stored in the r7 register
45   count = ig.input_cnt++;
46 
47   // In the following statement, the value of "input_cnt" stored in
48   // the r7 register is used, but it is wrong (never incremented).
49   return ig.input_cnt;
50 }
51 
testBug(void)52 void testBug(void)
53 {
54 #ifdef __SDCC
55 	ig.rx_byte = 0;
56 	ig.input_cnt = 1;
57 
58 	ASSERT (do_command() == 2);
59 	ASSERT (ig.input_cnt == 2);
60 	ASSERT (count == 1);
61 #endif
62 }
63