source: src/tests/dtor-early-exit.c @ 5479e63

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 5479e63 was 540b275, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

added labelled break on if statments to relevant tests

  • Property mode set to 100644
File size: 4.8 KB
Line 
1#include <fstream>
2#include <stdlib>
3extern "C" {
4#define false ((int)0)  // until stdbool.h works
5#define assert(cond) if (! (cond)) { sout | "Assertion failed: (" | #cond | ") at " __FILE__ | ":" | __LINE__ | endl; abort(); }
6}
7
8struct A {
9        char * name;
10        int * x;
11};
12
13// don't want these called
14void ?{}(A * a) { assert( false ); }
15void ?{}(A * a, char * name) { a->name = name; sout | "construct " | name | endl; a->x = malloc(); }
16void ?{}(A * a, char * name, int * ptr) { assert( false ); }
17
18A ?=?(A * a, A a) {  sout | "assign " | a->name | " " | a.name; return a; }
19void ?{}(A * a, A a) { sout | "copy construct " | a.name | endl; a->x = malloc(); }
20void ^?{}(A * a) { sout | "destruct " | a->name | endl; free(a->x); }
21
22// test returns
23void f(int i) {
24        sout | "f i=" | i | endl;
25        A x = { "x" };  // construct x
26        {
27                A y = { "y" }; // construct y
28                {
29                        A z = { "z" }; // construct z
30                        {
31                                if (i == 0) return; // destruct x, y, z
32                        }
33                        if (i == 1) return; // destruct x, y, z
34                        // destruct z
35                }
36                if (i == 2) return; // destruct x, y
37                // destruct y
38        }
39        return; // destruct x
40}
41
42// test loops, switch, etc.
43void g() {
44        for (int i = 0; i < 10; i++) {
45                sout | "g for i=" | i | endl;
46                A x = { "x" };
47                // construct x
48                // destruct x
49        }
50        sout | endl;
51        {
52                int i = 0;
53                while (i < 10) {
54                        sout | "g while i=" | i | endl;
55                        A x = { "x" };
56                        // construct x
57                        i++;
58                        // destruct x
59                }
60        }
61        sout | endl;
62        for (int i = 0; i < 10; i++) {
63                switch(10) {
64                        case 0:
65                        case 5:
66                        case 10: {
67                                A y = { "y" };
68                                sout | "g switch i=" | i | endl;
69                                // construct y
70                                break; // destruct y
71                        }
72                        default: {
73                                sout | "g switch i=" | i | endl;
74                                A x = { "x" };
75                                // construct x
76                                break; // destruct x
77                        }
78                }
79        }
80        sout | endl;
81        for (int k = 0; k < 2; k++) {
82                sout | "g for k=" | k | endl;
83                L1: for (int i = 0; i < 10; i++) {
84                        sout | "g for i=" | i | endl;
85
86                        A x = { "x" };
87                        if (i == 2) {
88                                sout | "continue L1" | endl;
89                                continue;  // destruct x
90                        } else if (i == 3) {
91                                sout | "break L1" | endl;
92                                break;  // destruct x
93                        }
94
95                        L2: for (int j = 0; j < 10; j++) {
96                                sout | "g for j=" | j | endl;
97                                A y = { "y" };
98                                if (j == 0) {
99                                        sout | "continue L2" | endl;
100                                        continue; // destruct y - missing because object that needs to be destructed is not a part of this block, it's a part of the for's block
101                                } else if (j == 1) {
102                                        sout | "break L2" | endl;
103                                        break;  // destruct y
104                                } else if (i == 1) {
105                                        sout | "continue L1" | endl;
106                                        continue L1; // destruct x,y - note: continue takes you to destructors for block, so only generate destructor for y
107                                } else if (k == 1) {
108                                        sout | "break L1" | endl;
109                                        break L1;  // destruct x,y
110                                }
111                        }
112                }
113        }
114
115        sout | endl;
116        L3: if( 3 ) {
117                A w = { "w" };
118                if( 4 ) {
119                        A v = { "v" };
120                        sout | "break L3" | endl;
121                        break L3;
122                }
123        }
124}
125
126// test goto
127void h() {
128        int i = 0;
129        // for each goto G with target label L:
130        // * find all constructed variables alive at G (set S_G)
131        // * find all constructed variables alive at L (set S_L)
132        // * if S_L-S_G is non-empty, error
133        // * emit destructors for all variables in S_G-S_L
134        sout | "h" | endl;
135        {
136                L0: ;
137#ifdef ERR1
138                        goto L1; // this is an error in g++ because it skips initialization of y
139#endif
140                        A y = { "y" };
141                        // S_L1 = { y }
142                L1: sout | "L1" | endl;
143                        A x = { "x" };
144                        // S_L2 = { y, x }
145                L2: sout | "L2" | endl;
146                        if (i == 0) {
147                                ++i;
148                                sout | "goto L1" | endl;
149                                // S_G = { y, x }
150                                goto L1;  // jump back, destruct b/c before x definition
151                                // S_L-S_G = {} => no error
152                                // S_G-S_L = { x } => destruct x
153                        } else if (i == 1) {
154                                ++i;
155                                sout | "goto L2" | endl;
156                                // S_G = { y, x }
157                                goto L2;  // jump back, do not destruct
158                                // S_L-S_G = {}
159                                // S_G-S_L = {} => destruct nothing
160                        } else if (i == 2) {
161                                ++i;
162                                sout | "goto L3" | endl;
163                                // S_G = { y, x }
164                                goto L3;  // jump ahead, do not destruct
165                                // S_L-S_G = {}
166                                // S_G-S_L = {}
167                        } else if (false) {
168                                ++i;
169                                A z = { "z" };
170                                sout | "goto L3-2" | endl;
171                                // S_G = { z, y, x }
172                                goto L3;
173                                // S_L-S_G = {}
174                                // S_G-S_L = {z} => destruct z
175                        } else {
176                                ++i;
177                                sout | "goto L4" | endl;
178                                // S_G = { y, x }
179                                goto L4;  // jump ahead, destruct b/c left block x was defined in
180                                // S_L-S_G = {}
181                                // S_G-S_L = { y, x } => destruct y, x
182                        }
183                        // S_L3 = { y, x }
184                L3: sout | "L3" | endl;
185                        sout | "goto L2-2" | endl;
186                        // S_G = { y, x }
187                        goto L2; // jump back, do not destruct
188                        // S_L-S_G = {}
189                        // S_G-S_L = {}
190        }
191        // S_L4 = {}
192        L4: sout | "L4" | endl;
193        if (i == 4) {
194                sout | "goto L0" | endl;
195                // S_G = {}
196                goto L0;
197                // S_L-S_G = {}
198                // S_G-S_L = {}
199        }
200        // S_G = {}
201#ifdef ERR2
202        if (i == 5) goto L2; // this is an error in g++ because it skips initialization of y, x
203        // S_L-S_G = { y, x } => non-empty, so error
204#endif
205}
206
207int main() {
208        sepDisable(sout);
209        for (int i = 0; i < 4; i++) {
210                f(i);
211        }
212        sout | endl;
213        g();
214        sout | endl;
215        h();
216}
Note: See TracBrowser for help on using the repository browser.