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

ADTast-experimental
Last change on this file since 1c80f20 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
RevLine 
[32b8144]1//
[5ead9f9]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.
[32b8144]6//
7// dtor-early-exit.c --
8//
[5ead9f9]9// Author           : Rob Schluntz
10// Created On       : Wed Aug 17 08:26:25 2016
11// Last Modified By : Peter A. Buhr
[5ea5b28]12// Last Modified On : Fri Dec 21 08:45:19 2018
13// Update Count     : 10
[32b8144]14//
[5ead9f9]15
[5a5d31a]16#include <fstream.hfa>
17#include <stdlib.hfa>
[e765794]18#include <assert.h>
[85f0713]19
20struct A {
[cdbfab0]21        const char * name;
[85f0713]22        int * x;
23};
24
25// don't want these called
[2afec66]26void ?{}(A & a) { assert( false ); }
[200fcb3]27void ?{}(A & a, const char * name) { a.name = name; sout | "construct " | name; a.x = (int*)malloc(); }
[2afec66]28void ?{}(A & a, const char * name, int * ptr) { assert( false ); }
[85f0713]29
[2afec66]30A ?=?(A & a, A b) {  sout | "assign " | a.name | " " | b.name; return a; }
[200fcb3]31void ?{}(A & a, A b) { sout | "copy construct " | b.name; a.x = (int*)malloc(); }
32void ^?{}(A & a) { sout | "destruct " | a.name; free(a.x); }
[85f0713]33
34// test returns
35void f(int i) {
[200fcb3]36        sout | "f i=" | i;
[85f0713]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++) {
[200fcb3]57                sout | "g for i=" | i;
[85f0713]58                A x = { "x" };
59                // construct x
60                // destruct x
61        }
[200fcb3]62        sout | nl;
[85f0713]63        {
64                int i = 0;
65                while (i < 10) {
[200fcb3]66                        sout | "g while i=" | i;
[85f0713]67                        A x = { "x" };
68                        // construct x
69                        i++;
70                        // destruct x
71                }
72        }
[5ea5b28]73        sout | nl;
[85f0713]74        for (int i = 0; i < 10; i++) {
75                switch(10) {
76                        case 0:
77                        case 5:
78                        case 10: {
79                                A y = { "y" };
[200fcb3]80                                sout | "g switch i=" | i;
[85f0713]81                                // construct y
82                                break; // destruct y
83                        }
84                        default: {
[200fcb3]85                                sout | "g switch i=" | i;
[85f0713]86                                A x = { "x" };
87                                // construct x
88                                break; // destruct x
89                        }
90                }
91        }
[200fcb3]92        sout | nl;
[85f0713]93        for (int k = 0; k < 2; k++) {
[200fcb3]94                sout | "g for k=" | k;
[85f0713]95                L1: for (int i = 0; i < 10; i++) {
[200fcb3]96                        sout | "g for i=" | i;
[85f0713]97
98                        A x = { "x" };
99                        if (i == 2) {
[200fcb3]100                                sout | "continue L1";
[85f0713]101                                continue;  // destruct x
102                        } else if (i == 3) {
[200fcb3]103                                sout | "break L1";
[85f0713]104                                break;  // destruct x
105                        }
106
107                        L2: for (int j = 0; j < 10; j++) {
[200fcb3]108                                sout | "g for j=" | j;
[85f0713]109                                A y = { "y" };
110                                if (j == 0) {
[200fcb3]111                                        sout | "continue L2";
[85f0713]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) {
[200fcb3]114                                        sout | "break L2";
[85f0713]115                                        break;  // destruct y
116                                } else if (i == 1) {
[200fcb3]117                                        sout | "continue L1";
[85f0713]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) {
[200fcb3]120                                        sout | "break L1";
[85f0713]121                                        break L1;  // destruct x,y
122                                }
123                        }
124                }
125        }
[540b275]126
[200fcb3]127        sout | nl;
[540b275]128        L3: if( 3 ) {
129                A w = { "w" };
130                if( 4 ) {
131                        A v = { "v" };
[200fcb3]132                        sout | "break L3";
[540b275]133                        break L3;
134                }
135        }
[85f0713]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
[200fcb3]146        sout | "h";
[85f0713]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 }
[200fcb3]154                L1: sout | "L1";
[85f0713]155                        A x = { "x" };
156                        // S_L2 = { y, x }
[200fcb3]157                L2: sout | "L2";
[85f0713]158                        if (i == 0) {
159                                ++i;
[200fcb3]160                                sout | "goto L1";
[85f0713]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;
[200fcb3]167                                sout | "goto L2";
[85f0713]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;
[200fcb3]174                                sout | "goto L3";
[85f0713]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" };
[200fcb3]182                                sout | "goto L3-2";
[85f0713]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;
[200fcb3]189                                sout | "goto L4";
[85f0713]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 }
[200fcb3]196                L3: sout | "L3";
197                        sout | "goto L2-2";
[85f0713]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 = {}
[200fcb3]204        L4: sout | "L4";
[85f0713]205        if (i == 4) {
[200fcb3]206                sout | "goto L0";
[85f0713]207                // S_G = {}
208                goto L0;
209                // S_L-S_G = {}
210                // S_G-S_L = {}
211        }
212#ifdef ERR2
[32b8144]213        // S_G = {}
[85f0713]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
[397c101a]219void i() {
220        // potential loop
221        for() {
222                if(true) continue;
223                int t = 0;
224        }
225}
226
[5809461]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
[85f0713]245int main() {
246        sepDisable(sout);
247        for (int i = 0; i < 4; i++) {
248                f(i);
249        }
[200fcb3]250        sout | nl;
[85f0713]251        g();
[200fcb3]252        sout | nl;
[85f0713]253        h();
[5809461]254
255        computedGoto();
[85f0713]256}
[5ead9f9]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.