source: src/tests/raii/dtor-early-exit.c @ 8573729

resolv-new
Last change on this file since 8573729 was 80e8582, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Move constructor/destructor tests to raii subdirectory

  • Property mode set to 100644
File size: 5.7 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// dtor-early-exit.c --
8//
9// Author           : Rob Schluntz
10// Created On       : Wed Aug 17 08:26:25 2016
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Wed Aug 17 08:29:37 2016
13// Update Count     : 2
14//
15
16#include <fstream>
17#include <stdlib>
18extern "C" {
19#define false ((int)0)  // until stdbool.h works
20#define assert(cond) if (! (cond)) { sout | "Assertion failed: (" | #cond | ") at " __FILE__ | ":" | __LINE__ | endl; abort(); }
21}
22
23struct A {
24        const char * name;
25        int * x;
26};
27
28// don't want these called
29void ?{}(A & a) { assert( false ); }
30void ?{}(A & a, const char * name) { a.name = name; sout | "construct " | name | endl; a.x = (int*)malloc(); }
31void ?{}(A & a, const char * name, int * ptr) { assert( false ); }
32
33A ?=?(A & a, A b) {  sout | "assign " | a.name | " " | b.name; return a; }
34void ?{}(A & a, A b) { sout | "copy construct " | b.name | endl; a.x = (int*)malloc(); }
35void ^?{}(A & a) { sout | "destruct " | a.name | endl; free(a.x); }
36
37// test returns
38void f(int i) {
39        sout | "f i=" | i | endl;
40        A x = { "x" };  // construct x
41        {
42                A y = { "y" }; // construct y
43                {
44                        A z = { "z" }; // construct z
45                        {
46                                if (i == 0) return; // destruct x, y, z
47                        }
48                        if (i == 1) return; // destruct x, y, z
49                        // destruct z
50                }
51                if (i == 2) return; // destruct x, y
52                // destruct y
53        }
54        return; // destruct x
55}
56
57// test loops, switch, etc.
58void g() {
59        for (int i = 0; i < 10; i++) {
60                sout | "g for i=" | i | endl;
61                A x = { "x" };
62                // construct x
63                // destruct x
64        }
65        sout | endl;
66        {
67                int i = 0;
68                while (i < 10) {
69                        sout | "g while i=" | i | endl;
70                        A x = { "x" };
71                        // construct x
72                        i++;
73                        // destruct x
74                }
75        }
76        sout | endl;
77        for (int i = 0; i < 10; i++) {
78                switch(10) {
79                        case 0:
80                        case 5:
81                        case 10: {
82                                A y = { "y" };
83                                sout | "g switch i=" | i | endl;
84                                // construct y
85                                break; // destruct y
86                        }
87                        default: {
88                                sout | "g switch i=" | i | endl;
89                                A x = { "x" };
90                                // construct x
91                                break; // destruct x
92                        }
93                }
94        }
95        sout | endl;
96        for (int k = 0; k < 2; k++) {
97                sout | "g for k=" | k | endl;
98                L1: for (int i = 0; i < 10; i++) {
99                        sout | "g for i=" | i | endl;
100
101                        A x = { "x" };
102                        if (i == 2) {
103                                sout | "continue L1" | endl;
104                                continue;  // destruct x
105                        } else if (i == 3) {
106                                sout | "break L1" | endl;
107                                break;  // destruct x
108                        }
109
110                        L2: for (int j = 0; j < 10; j++) {
111                                sout | "g for j=" | j | endl;
112                                A y = { "y" };
113                                if (j == 0) {
114                                        sout | "continue L2" | endl;
115                                        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
116                                } else if (j == 1) {
117                                        sout | "break L2" | endl;
118                                        break;  // destruct y
119                                } else if (i == 1) {
120                                        sout | "continue L1" | endl;
121                                        continue L1; // destruct x,y - note: continue takes you to destructors for block, so only generate destructor for y
122                                } else if (k == 1) {
123                                        sout | "break L1" | endl;
124                                        break L1;  // destruct x,y
125                                }
126                        }
127                }
128        }
129
130        sout | endl;
131        L3: if( 3 ) {
132                A w = { "w" };
133                if( 4 ) {
134                        A v = { "v" };
135                        sout | "break L3" | endl;
136                        break L3;
137                }
138        }
139}
140
141// test goto
142void h() {
143        int i = 0;
144        // for each goto G with target label L:
145        // * find all constructed variables alive at G (set S_G)
146        // * find all constructed variables alive at L (set S_L)
147        // * if S_L-S_G is non-empty, error
148        // * emit destructors for all variables in S_G-S_L
149        sout | "h" | endl;
150        {
151                L0: ;
152#ifdef ERR1
153                        goto L1; // this is an error in g++ because it skips initialization of y
154#endif
155                        A y = { "y" };
156                        // S_L1 = { y }
157                L1: sout | "L1" | endl;
158                        A x = { "x" };
159                        // S_L2 = { y, x }
160                L2: sout | "L2" | endl;
161                        if (i == 0) {
162                                ++i;
163                                sout | "goto L1" | endl;
164                                // S_G = { y, x }
165                                goto L1;  // jump back, destruct b/c before x definition
166                                // S_L-S_G = {} => no error
167                                // S_G-S_L = { x } => destruct x
168                        } else if (i == 1) {
169                                ++i;
170                                sout | "goto L2" | endl;
171                                // S_G = { y, x }
172                                goto L2;  // jump back, do not destruct
173                                // S_L-S_G = {}
174                                // S_G-S_L = {} => destruct nothing
175                        } else if (i == 2) {
176                                ++i;
177                                sout | "goto L3" | endl;
178                                // S_G = { y, x }
179                                goto L3;  // jump ahead, do not destruct
180                                // S_L-S_G = {}
181                                // S_G-S_L = {}
182                        } else if (false) {
183                                ++i;
184                                A z = { "z" };
185                                sout | "goto L3-2" | endl;
186                                // S_G = { z, y, x }
187                                goto L3;
188                                // S_L-S_G = {}
189                                // S_G-S_L = {z} => destruct z
190                        } else {
191                                ++i;
192                                sout | "goto L4" | endl;
193                                // S_G = { y, x }
194                                goto L4;  // jump ahead, destruct b/c left block x was defined in
195                                // S_L-S_G = {}
196                                // S_G-S_L = { y, x } => destruct y, x
197                        }
198                        // S_L3 = { y, x }
199                L3: sout | "L3" | endl;
200                        sout | "goto L2-2" | endl;
201                        // S_G = { y, x }
202                        goto L2; // jump back, do not destruct
203                        // S_L-S_G = {}
204                        // S_G-S_L = {}
205        }
206        // S_L4 = {}
207        L4: sout | "L4" | endl;
208        if (i == 4) {
209                sout | "goto L0" | endl;
210                // S_G = {}
211                goto L0;
212                // S_L-S_G = {}
213                // S_G-S_L = {}
214        }
215#ifdef ERR2
216        // S_G = {}
217        if (i == 5) goto L2; // this is an error in g++ because it skips initialization of y, x
218        // S_L-S_G = { y, x } => non-empty, so error
219#endif
220}
221
222// TODO: implement __label__ and uncomment these lines
223void computedGoto() {
224  // __label__ bar;
225  void *ptr;
226  ptr = &&foo;
227  goto *ptr;
228  assert(false);
229foo: ;
230//   void f() {
231//     ptr = &&bar;
232//     goto *ptr;
233//     assert(false);
234//   }
235//   f();
236//   assert(false);
237// bar: ;
238}
239
240int main() {
241        sepDisable(sout);
242        for (int i = 0; i < 4; i++) {
243                f(i);
244        }
245        sout | endl;
246        g();
247        sout | endl;
248        h();
249
250        computedGoto();
251}
252
253// Local Variables: //
254// tab-width: 4 //
255// compile-command: "cfa dtor-early-exit" //
256// End: //
Note: See TracBrowser for help on using the repository browser.