source: src/tests/dtor-early-exit.c@ 8688ce1

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 8688ce1 was 540b275, checked in by Thierry Delisle <tdelisle@…>, 9 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.