source: src/tests/dtor-early-exit.c@ 7fe4cc3e

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 7fe4cc3e was 85f0713, checked in by Rob Schluntz <rschlunt@…>, 9 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.