source: src/tests/dtor-early-exit.c @ 85f0713

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglergc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 85f0713 was 85f0713, checked in by Rob Schluntz <rschlunt@…>, 6 years ago

add init_once and dtor-early-exit tests

  • Property mode set to 100644
File size: 4.7 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
116// test goto
117void h() {
118        int i = 0;
119        // for each goto G with target label L:
120        // * find all constructed variables alive at G (set S_G)
121        // * find all constructed variables alive at L (set S_L)
122        // * if S_L-S_G is non-empty, error
123        // * emit destructors for all variables in S_G-S_L
124        sout | "h" | endl;
125        {
126                L0: ;
127#ifdef ERR1
128                        goto L1; // this is an error in g++ because it skips initialization of y
129#endif
130                        A y = { "y" };
131                        // S_L1 = { y }
132                L1: sout | "L1" | endl;
133                        A x = { "x" };
134                        // S_L2 = { y, x }
135                L2: sout | "L2" | endl;
136                        if (i == 0) {
137                                ++i;
138                                sout | "goto L1" | endl;
139                                // S_G = { y, x }
140                                goto L1;  // jump back, destruct b/c before x definition
141                                // S_L-S_G = {} => no error
142                                // S_G-S_L = { x } => destruct x
143                        } else if (i == 1) {
144                                ++i;
145                                sout | "goto L2" | endl;
146                                // S_G = { y, x }
147                                goto L2;  // jump back, do not destruct
148                                // S_L-S_G = {}
149                                // S_G-S_L = {} => destruct nothing
150                        } else if (i == 2) {
151                                ++i;
152                                sout | "goto L3" | endl;
153                                // S_G = { y, x }
154                                goto L3;  // jump ahead, do not destruct
155                                // S_L-S_G = {}
156                                // S_G-S_L = {}
157                        } else if (false) {
158                                ++i;
159                                A z = { "z" };
160                                sout | "goto L3-2" | endl;
161                                // S_G = { z, y, x }
162                                goto L3;
163                                // S_L-S_G = {}
164                                // S_G-S_L = {z} => destruct z
165                        } else {
166                                ++i;
167                                sout | "goto L4" | endl;
168                                // S_G = { y, x }
169                                goto L4;  // jump ahead, destruct b/c left block x was defined in
170                                // S_L-S_G = {}
171                                // S_G-S_L = { y, x } => destruct y, x
172                        }
173                        // S_L3 = { y, x }
174                L3: sout | "L3" | endl;
175                        sout | "goto L2-2" | endl;
176                        // S_G = { y, x }
177                        goto L2; // jump back, do not destruct
178                        // S_L-S_G = {}
179                        // S_G-S_L = {}
180        }
181        // S_L4 = {}
182        L4: sout | "L4" | endl;
183        if (i == 4) {
184                sout | "goto L0" | endl;
185                // S_G = {}
186                goto L0;
187                // S_L-S_G = {}
188                // S_G-S_L = {}
189        }
190        // S_G = {}
191#ifdef ERR2
192        if (i == 5) goto L2; // this is an error in g++ because it skips initialization of y, x
193        // S_L-S_G = { y, x } => non-empty, so error
194#endif
195}
196
197int main() {
198        sepDisable(sout);
199        for (int i = 0; i < 4; i++) {
200                f(i);
201        }
202        sout | endl;
203        g();
204        sout | endl;
205        h();
206}
207
Note: See TracBrowser for help on using the repository browser.