source: tests/raii/dtor-early-exit.cfa @ a32a887

ADTast-experimental
Last change on this file since a32a887 was 397c101a, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Fix bug where 'continue' would incorrectly claim to skip initialization Fixes #150?

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