|
|
1.1 root 1: /*ident "@(#)ctrans:src/simpl2.c 1.13" */
2: /******************************************************************
3:
4: C++ source for cfront, the C++ compiler front-end
5: written in the computer science research center of Bell Labs
6:
7: Copyright (c) 1984 AT&T, Inc. All rights Reserved
8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9:
10: simpl2.c:
11:
12: simplify the typechecked function
13: remove: classes:
14: class fct-calls
15: operators
16: value constructors and destructors
17: new and delete operators (replace with function calls)
18: initializers (turn them into statements)
19: constant expressions (evaluate them)
20: inline functions (expand the calls)
21: enums (make const ints)
22: unreachable code (delete it)
23: make implicit coersions explicit
24:
25: in general you cannot simplify something twice
26:
27: *******************************************************************/
28:
29: #include "cfront.h"
30: #include "size.h"
31: #include <ctype.h>
32:
33: extern Pname Ntmp;
34: extern Pnlist inllist;
35: Pname find_vptr(Pclass);
36: extern is_probably_temp(char*);
37:
38: extern int no_of_returns;
39:
40: extern Pname new_fct;
41: //extern Pname del_fct;
42:
43: extern Pstmt del_list;
44: extern Pstmt break_del_list;
45: extern Pstmt continue_del_list;
46:
47: extern Pname curr_fct; // current function
48: extern Pexpr init_list;
49: extern int imeasure;
50:
51: Pexpr cdvec(Pname f, Pexpr vec, Pclass cl, Pname cd, int tail, Pexpr i, Pexpr vec2)
52: /*
53: generate a call to construct or destroy the elements of a vector
54: */
55: {
56: Pexpr sz = new texpr(SIZEOF,cl,0); // sizeof elem
57: sz->tp = uint_type;
58: (void) cl->tsizeof();
59:
60: Pexpr esz = new texpr(SIZEOF,cl,0); // noe = sizeof(vec)/sizeof(elem)
61: esz->tp = int_type;
62:
63: Pexpr noe;
64: if (vec2)
65: noe = new texpr(SIZEOF,vec2->tp,0);
66: else noe = new texpr(SIZEOF,vec->tp,0);
67:
68: // Pexpr noe = new texpr(SIZEOF,vec->tp,0);
69: noe->tp = int_type;
70: noe = new expr(DIV,noe,esz);
71: noe->tp = uint_type;
72: // error('d',"cdvec tail %d i %d",tail,i);
73: // Pexpr arg = (0<=tail) ? new expr(ELIST,zero,0) : 0; // 0 or 1 for dtors
74: Pexpr arg = (i) ? new expr(ELIST,i,0) : 0;
75: arg = (0<=tail) ? new expr(ELIST,zero,arg) : arg; // 0 or 1 for dtors
76: arg = new expr(ELIST,cd,arg); // constructor or destructor
77: cd->lval(ADDROF); // cd->take_addr();
78:
79: arg = new expr(ELIST,sz,arg);
80: arg = new expr(ELIST,noe,arg);
81: arg = new expr(ELIST,vec,arg);
82:
83: arg = new call(f,arg);
84: arg->base = G_CALL;
85: arg->fct_name = f;
86:
87: return arg;
88: }
89:
90: /*
91: int new_used; // pre-define new and delete only if the user didn't
92:
93: void new_init()
94: {
95: char* ns = oper_name(NEW);
96: char* ds = oper_name(DELETE);
97:
98: new_used = 1;
99:
100: new_fct = gtbl->look(ns,0);
101: del_fct = gtbl->look(ds,0);
102:
103: if (new_fct && !del_fct)
104: error('w',"%n defined but not operator delete()",new_fct);
105: if (del_fct && !new_fct)
106: error('w',"%n defined but not operator new()",del_fct);
107:
108: if (Pfct(new_fct->tp)->body==0) new_fct->dcl_print(0);
109: if (Pfct(del_fct->tp)->body==0) del_fct->dcl_print(0);
110: }
111: */
112: Pstmt trim_tail(Pstmt tt)
113: /*
114: strip off statements after RETURN etc.
115: NOT general: used for stripping off spurious destructor calls
116: */
117: {
118: if (tt == 0) return 0;
119:
120: while (tt->s_list) {
121: Pstmt tpx;
122: switch (tt->base) {
123: case PAIR:
124: tpx = trim_tail(tt->s2);
125: goto tpxl;
126: case BLOCK:
127: tpx = trim_tail(tt->s);
128: tpxl:
129: if (tpx == 0) return 0;
130:
131: switch (tpx->base) {
132: case SM:
133: break;
134: case CONTINUE:
135: case BREAK:
136: case GOTO:
137: case RETURN:
138: if (tt->s_list->base != LABEL) tt->s_list = 0;
139: default:
140: return tpx;
141: }
142: default:
143: if (tt = tt->s_list) break;
144: return 0;
145: case RETURN:
146: if (tt->s_list->base != LABEL) tt->s_list = 0;
147: return tt;
148: }
149: }
150:
151: switch (tt->base) {
152: case PAIR: return trim_tail(tt->s2);
153: // case LABEL: return trim_tail(tt->s);
154: case BLOCK: if (tt->s) return trim_tail(tt->s);
155: default: return tt;
156: }
157: }
158:
159: extern Ptype Pfct_type;
160:
161: Pexpr mptr_assign(Pexpr n, Pexpr in)
162: {
163: Pexpr i1;
164: Pexpr i2;
165: Pexpr i3;
166:
167: if ( n->base == NAME )
168: Pname(n)->use();
169:
170: if (in->base == NAME) {
171: i1 = new mdot("d",in);
172: i1->i1 = 9;
173: i2 = new mdot("i",in);
174: i2->i1 = 9;
175: i3 = new mdot("f",in);
176: i3->i1 = 9;
177: }
178: else {
179: i1 = in->e1->e1;
180: i2 = in->e1->e2;
181: i3 = in->e2;
182: }
183: Pexpr nd = new mdot("d",n);
184: nd->i1 = 9;
185: Pexpr e1 = new expr(ASSIGN,nd,i1);
186:
187: Pexpr ni = new mdot("i",n);
188: ni->i1 = 9;
189: Pexpr e2 = new expr(ASSIGN,ni,i2);
190:
191: Pexpr nf = new mdot("f",n);
192: nf->i1 = 9;
193: // Pexpr ii = in->e2; //new cast(Pfct_type,in->e2);
194: Pexpr e3 = new expr(ASSIGN,nf,i3);
195:
196: Pexpr ee = new expr(CM,e2,e3);
197: return new expr(CM,e1,ee);
198: }
199:
200: /*
201: * to move up dtors in && and || expressions
202: * need to keep track of temporaries handled
203: * not to destroy twice :: recognized in expr::typ
204: * actual rewriting is initiated in stmt::simpl
205: * need_lift_dtors(): predicate: yes, proceed
206: * make_dtor_expr(): create dtor expr
207: * find_temps_in_expr(): temporaries to make_dtor
208: * lift_dtor(): actually rewrite the &&/|| expression
209: */
210: static Ptable tmp_tbl = new table(CTBLSIZE,0,0);
211: static Pname tmp_list;
212: static Ptable Ntmp_tbl; // if Cstmt set, use Cstmt->memtbl
213: static bit need_lift;
214: Pexpr Ntmp_dtor;
215:
216: static bit
217: need_lift_dtors(Pexpr e)
218: { // confirm that expression requires lifting
219: // error('d',"need_lift_dtors( %d %k )", e, e->base);
220: Pexpr ee, ex;
221:
222: for (ex = Ntmp_dtor; ex; ex = ex->e2) {
223: ee = ex->e1;
224: if ( ee == e ) break;
225: }
226: if ( !ex ) return 0;
227: return 1;
228: }
229:
230: static Pexpr
231: make_dtor_expr(Pname nl)
232: {
233: Pexpr dl=0;
234: Pname n;
235:
236: for (n = nl; n; n=n->n_list) {
237: // error('d',"make_dtor_expr: nl: %n", n );
238: // if (tmp_tbl->look(n->string,0)) continue;
239: tmp_tbl->insert(n,DUMMY);
240: Pname cln = n->tp->is_cl_obj();
241: Pname d = Pclass(cln->tp)->has_dtor();
242: Pexpr e = call_dtor(n,d,0,DOT,one);
243: if (dl == 0 )
244: dl = e;
245: else {
246: dl = new expr(CM,dl,e);
247: dl->tp = e->tp;
248: }
249: }
250: dl->simpl();
251: return dl;
252: }
253:
254: static void
255: find_temps_in_expr(Pexpr e, char *s=0)
256: {
257: if ( e == 0 ) return;
258:
259: switch ( e->base ) {
260: case QUEST:
261: if (s && tmp_list) return;
262: find_temps_in_expr( e->cond,s ); // no break
263: default:
264: if (s && tmp_list) return;
265: find_temps_in_expr( e->e1,s );
266: if (s && tmp_list) return;
267: find_temps_in_expr( e->e2,s );
268: return;
269: case REF: case DOT:
270: if (s && tmp_list) return;
271: find_temps_in_expr( e->e1,s ); // no break
272: case MDOT:
273: // find_temps_in_expr( e->mem ); // no break
274: case SIZEOF: case ZERO:
275: case TNAME: case STRING:
276: case ICON: case ID:
277: case FCON: case CCON:
278: case IVAL: case BLOCK:
279: return;
280: case NAME:
281: Pname n = Pname(e);
282: Pname cln = n->tp->is_cl_obj();
283: if (cln &&
284: Pclass(cln->tp)->has_dtor() &&
285: is_probably_temp(n->string) )
286: {
287: // error('d',"find_temps_in_expr n %n s %s", n,s);
288:
289: if (s) {
290: if (strcmp(s,n->string)==0)
291: tmp_list = n;
292: return;
293: }
294:
295: if (tmp_list==0)
296: tmp_list = n;
297: else {
298: Pname nn = tmp_list;
299: if ( n == nn ) return;
300: while (nn->n_list) {
301: nn=nn->n_list;
302: if ( n == nn ) return;
303: }
304: nn->n_list = n;
305: }
306: }
307: return;
308: }
309: }
310:
311: static bit
312: find_in_Ntmp(char *s)
313: { // does `s' occur within Ntmp
314: // error('d',"find_in_ntmp( %s )", s);
315: Pexpr ee, ex;
316:
317: tmp_list = 0;
318: for (ex = Ntmp_dtor; ex; ex = ex->e2) {
319: ee = ex->e1;
320: find_temps_in_expr(ee,s);
321: if (tmp_list) { tmp_list = 0; return 1; }
322: }
323: return 0;
324: }
325:
326: static Pexpr
327: lift_dtors(Pexpr e, Ptable tbl)
328: {
329: // find class object temporaries in expression
330: tmp_list = 0; find_temps_in_expr( e->e1 );
331: Pname n1 = tmp_list; tmp_list = 0;
332:
333: find_temps_in_expr( e->e2 );
334: Pname n2 = tmp_list; tmp_list = 0;
335:
336: // generate dtor calls and rewrite expressions
337: Pexpr dl = make_dtor_expr(n1);
338:
339: // error('d',"lift_dtor: e: tp %k e1->tp %k scope %d",e->tp->base,e->e1->tp->base,scope);
340: if (tbl == 0) tbl = scope;
341:
342: Ptype t = 0;
343: Pname tmp = 0;
344: Pexpr ex;
345:
346: if (dl) {
347: t = e->e1->tp;
348: tmp = make_tmp('Q',t,tbl);
349: tmp->n_assigned_to++;
350: ex = new expr(ASSIGN,tmp,e->e1); ex->tp = t;
351: e->e1 = ex; e->e1->tp =t;
352: e->e1 = new expr(CM,e->e1,dl); e->e1->tp = dl->tp;
353: e->e1 = new expr(CM,e->e1,tmp); e->e1->tp =t;
354: }
355:
356: dl = make_dtor_expr(n2);
357:
358: if (dl) {
359: // reuse same temp if possible
360: if ( e->e2->tp != t ) {
361: t = e->e1->tp;
362: tmp = make_tmp('Q',t,tbl);
363: }
364: tmp->n_assigned_to++;
365: ex = new expr(ASSIGN,tmp,e->e2); ex->tp = t;
366: e->e2 = ex; e->e2->tp =t;
367: e->e2 = new expr(CM,e->e2,dl); e->e2->tp = dl->tp;
368: e->e2 = new expr(CM,e->e2,tmp); e->e2->tp =t;
369: }
370:
371: return e;
372: }
373:
374: Pstmt block::simpl()
375: {
376: int i;
377: Pname n;
378: Pstmt ss=0, sst=0;
379: Pstmt dd=0, ddt=0;
380: Pstmt stail;
381: Ptable old_scope = scope;
382: need_lift = 0;
383: tmp_tbl->reinit();
384:
385: DB( if(Sdebug>=1)
386: error('d',"%d->block::simple() own_tbl %d memtbl %d curr_fct%n",this,own_tbl,memtbl,curr_fct);
387: );
388: // error('d',"%d->block::simpl() own_tbl %d memtbl %d curr_fct%n",this,own_tbl,memtbl,curr_fct);
389: if (own_tbl == 0) {
390: ss = (s) ? s->simpl() : 0;
391: return ss;
392: }
393:
394: scope = memtbl;
395: if (scope->init_stat == 0) scope->init_stat = 1; /* table is simplified. */
396:
397: for (n=scope->get_mem(i=1); n; n=scope->get_mem(++i)) {
398: Pstmt st = 0;
399: Pname cln;
400: Pexpr in = n->n_initializer;
401: // error('d',"local %k %n in %k %t",n->n_sto,n,in?in->base:0,in?in->tp:0);
402: if (in || n->n_evaluated) {
403: scope->init_stat = 2; /* initializer in this scope */
404: if (n->n_sto == EXTERN) {
405: error(&n->where,"Id local extern%n",n);
406: continue;
407: }
408: }
409:
410: switch (n->n_scope) {
411: case ARG:
412: case 0:
413: case PUBLIC:
414: continue;
415: }
416:
417: if (n->n_stclass == STATIC) { // local static class object
418: /* initialization of local static objects;
419: * set up first pass switch
420: * temp_switch ? 0
421: * : (stat_obj=init_expr, temp_switch=1);
422: *
423: * ARGS: temporary class object in init_expr with dtor
424: * must call dtor once in std function
425: */
426:
427: if ((in==0 && n->n_scope==ARGS) ||
428: (in && in->base==STAT_INIT))
429: {
430: Pname cn;
431: Pname x;
432: Ptype ct;
433: int vec_seen = 0;
434:
435: cn = n->tp->is_cl_obj();
436: if ( cn == 0 ) { ++vec_seen; cn = cl_obj_vec; }
437:
438: if ( cn ) {
439: ct = new ptr(PTR,vec_seen?Pvec(n->tp)->typ:n->tp);
440: x = make_tmp('F', ct, gtbl );
441: x->n_initializer = zero;
442: }
443: else
444: x = make_tmp('F',int_type,scope);
445:
446: x->n_sto = n->n_stclass = STATIC;
447:
448: if (in) {
449: if (in->e2)
450: in->base = ASSIGN;
451: else in = in->e1;
452: }
453:
454: Pexpr set;
455: if ( cn ) {
456: x->dcl_print(0);
457: Pclass cl = Pclass(cn->tp);
458: Pname dtor = cl->has_dtor();
459:
460: Pexpr cc;
461: if ( dtor ) {
462: if ( vec_seen == 0 ) {
463: Pexpr eee = new expr(DEREF, x, 0 );
464: Pexpr c = call_dtor(eee,dtor,0,DOT,one);
465: c->tp = any_type;
466: cc = new expr( QUEST, c, zero );
467: cc->cond = x;
468: }
469: else cc = cdvec(vec_del_fct,x,cl,dtor,0,zero,n);
470: cc->tp = any_type; // arghh!
471:
472: Pstmt dls = new estmt( SM, n->where, cc, 0 );
473: if ( st_dlist ) dls->s_list = st_dlist;
474: st_dlist = dls;
475: }
476:
477: Pexpr xe;
478: if (cn) {
479: if ( vec_seen == 0 )
480: xe = new expr( G_ADDROF, 0, n );
481: else {
482: Pexpr ee = new expr( DEREF, n, zero );
483: xe = new expr( G_ADDROF, 0, ee );
484: }
485: }
486:
487: set = new expr(ASSIGN,x,xe);
488: set->tp = ct;
489: }
490: else {
491: set = new expr(ASSIGN,x,one);
492: set->tp = int_type;
493: }
494:
495: // set pointer to static object and continue.
496: // sorry for goto, but beats rewriting code.
497: if ( n->n_scope == ARGS && in == 0 ) {
498: set = new expr( QUEST, zero, set );
499: set->cond = x;
500: st = new estmt(SM,n->where,set,0);
501: goto init_stat3;
502: }
503:
504: in = new expr(G_CM,in,set);
505: in = new expr(STAT_INIT,zero,in);
506: in->cond = x;
507: }
508: else
509: continue;
510: }
511:
512: if ( in ) {
513: if ((in->base == ILIST && in->e2 == 0) ||
514: (in->base == STRING && n->tp->base == VEC))
515: if (ansi_opt==0) {
516: error('s',&n->where,"initialization of%n (automatic aggregate)",n);
517: continue;
518: }
519: else {
520: n->n_initializer=in;
521: continue;
522: }
523: }
524:
525: if (ansi_opt && in && n->tp->tconst()) {
526: n->n_initializer=in;
527: continue;
528: }
529:
530: if (n->tp == 0) continue; /* label */
531: if (n->n_evaluated) continue;
532:
533: // error('d',"***** block::simpl: %n->check",n);
534: // construction and destruction of temporaries is handled locally
535: // `D' :: int; X; ==> generates int __D<some_number> */
536: // note: does not appear necessary since all go to int
537: {
538: char* s = n->string;
539: register char c3 = s[3];
540: if (s[0]=='_' && s[1]=='_' && s[2]=='D' && isdigit(c3))
541: continue;
542: }
543:
544: if ( cln=n->tp->is_cl_obj() ) {
545: Pclass cl = Pclass(cln->tp);
546: Pname d = cl->has_dtor();
547:
548: if ( n->n_stclass == STATIC // local static class object
549: && in && in->base==STAT_INIT )
550: goto stat_init;
551:
552: if (d) { // n->cl.dtor(0);
553: // error('d',"***** block::simpl: %n->%t.dtor(0)",n,cl);
554: // special case: int i = foo() && foo();
555: // dtors hoisted within stmt::simpl, called below ...
556: if ( Ntmp_dtor &&
557: is_probably_temp(n->string) &&
558: find_in_Ntmp(n->string))
559: continue;
560:
561:
562: Pexpr dl = call_dtor(n,d,0,DOT,one);
563: // Pstmt dls = new estmt(SM,n->where,dl,0);
564: Pstmt dls = new estmt(SM,no_where,dl,0);
565: if (dd) {
566: dls->s_list = dd;
567: dd = dls;
568: }
569: else
570: ddt = dd = dls;
571: }
572:
573: // error('d',"%n: in %d",n,in?in->base:0);
574: if (in) {
575: switch (in->base) {
576: case DEREF: // *constructor?
577: if (in->e1->base == G_CALL) {
578: Pname fn = in->e1->fct_name;
579: if (fn==0 || fn->n_oper!=CTOR) goto ddd;
580: st = new estmt(SM,n->where,in->e1,0);
581: n->n_initializer = 0;
582: break;
583: }
584: goto ddd;
585: case STAT_INIT:
586: stat_init:
587: // error('d', "block::simpl: case #1 stat_init : n: %n", n );
588: in->base = QUEST;
589: st = new estmt(SM,n->where,in,0);
590: n->n_initializer = 0;
591: break;
592: case G_CM:
593: st = new estmt(SM,n->where,in->e1,0);
594: n->n_initializer = 0;
595: break;
596: case ASSIGN: // assignment to "n"?
597: if (in->e1 == n) {
598: st = new estmt(SM,n->where,in,0);
599: n->n_initializer = 0;
600: break;
601: }
602: default:
603: goto ddd;
604: }
605: }
606: }
607: else if (cl_obj_vec) {
608: Pclass cl = Pclass(cl_obj_vec->tp);
609: Pname d = cl->has_dtor();
610: Pname c = cl->has_ictor();
611: n->n_initializer = 0;
612:
613: if ( n->n_stclass == STATIC // local static class object
614: && in && in->base==STAT_INIT )
615: goto stat_init2;
616:
617: if (c) { // _vec_new(vec,noe,sz,ctor);
618: if (in==0 || in->base==ILIST) {
619: Pexpr a = cdvec(vec_new_fct,n,cl,c,-1,0);
620: st = new estmt(SM,n->where,a,0);
621: }
622: else
623: st = new estmt(SM,n->where,in,0);
624: }
625: // no default ctor but provided all elements with argument
626: else if ( in ) st = new estmt(SM,n->where,in,0);
627:
628:
629: if (d) { // __vec_delete(vec,noe,sz,dtor,0);
630: Pfct f = Pfct(d->tp);
631: int i = 0;
632: for (Pname nn = f->f_args->n_list;
633: nn && nn->n_list; nn=nn->n_list) i++;
634: Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i));
635: // Pstmt dls = new estmt(SM,n->where,a,0);
636: Pstmt dls = new estmt(SM,no_where,a,0);
637: if (dd) {
638: dls->s_list = dd;
639: dd = dls;
640: }
641: else
642: ddt = dd = dls;
643: }
644: }
645: else if (in) {
646: switch (in->base) {
647: case ILIST:
648: switch (n->n_scope) {
649: case FCT:
650: if (in->e2) { // pointer to member
651: Pexpr ee = mptr_assign(n,in);
652: st = new estmt(SM,n->where,ee,0);
653: n->n_initializer = 0;
654: break;
655: }
656: case ARG:
657: if (ansi_opt == 0) error('s',"Ir list for localV%n",n);
658: }
659: break;
660: case STAT_INIT:
661: stat_init2:
662: // error('d', "block::simpl: case #2 stat_init : n: %n", n );
663: in->base = QUEST;
664: st = new estmt(SM,n->where,in,0);
665: n->n_initializer = 0;
666: break;
667: case STRING:
668: if (n->tp->base==VEC) break; /* BUG char vec only */
669: default:
670: ddd:
671: { Pexpr ee = new expr(ASSIGN,n,in);
672: st = new estmt(SM,n->where,ee,0);
673: n->n_initializer = 0;
674: }
675: }
676: }
677:
678: init_stat3: if (st) {
679: if (ss)
680: sst->s_list = st;
681: else
682: ss = st;
683: sst = st;
684: }
685: }
686:
687: if (dd) {
688: Pstmt od = del_list;
689: Pstmt obd = break_del_list;
690: Pstmt ocd = continue_del_list;
691:
692: dd->simpl();
693: del_list = (od) ? Pstmt(new pair(curloc,dd,od)) : dd;
694: break_del_list = (break_del_list&&obd) ? Pstmt(new pair(curloc,dd,obd)) : dd;
695: continue_del_list = (continue_del_list&&ocd) ? Pstmt(new pair(curloc,dd,ocd)) : dd;
696:
697: stail = s ? s->simpl() : 0;
698:
699: Pfct f = Pfct(curr_fct->tp);
700: if (this!=f->body
701: || f->returns->base==VOID
702: || (f->returns->base!=VOID && no_of_returns==0 ) // you have been warned!
703: || strcmp(curr_fct->string,"main")==0 ) {
704: // not dropping through the bottom of a value returning function
705: if (stail) {
706: Pstmt tt = (stail->base==RETURN || stail->base==LABEL) ? stail : trim_tail(stail);
707: if (tt && tt->base != RETURN) stail->s_list = dd;
708: }
709: else
710: s = dd;
711: stail = ddt;
712: }
713:
714: del_list = od;
715: continue_del_list = ocd;
716: break_del_list = obd;
717: }
718: else
719: stail = s ? s->simpl() : 0;
720:
721: if (ss) { /* place constructor calls */
722: ss->simpl();
723: sst->s_list = s;
724: s = ss;
725: if (stail == 0) stail = sst;
726: }
727:
728: need_lift = 0;
729: scope = old_scope;
730:
731: return stail;
732: }
733:
734: int no_sizeof;
735: void expr::simpl()
736: {
737: DB(if(Sdebug>=2){
738: error('d',"%d->expr::simpl() %k",this,this?base:0);
739: if(Sdebug>=3) display_expr(this);
740: });
741: if (this==0 || permanent==2) return; // already expanded
742: static TOK obase = 0;
743:
744: switch (base) {
745: case MDOT:
746: obase = base;
747: mem->simpl();
748: obase = 0;
749: // no break
750:
751: case ICALL: // already expanded
752: return;
753:
754: case G_ADDROF:
755: case ADDROF:
756: // error('d',"simpl & %k",e2->base);
757:
758: e2->simpl();
759: switch (e2->base) {
760: case DOT:
761: case REF:
762: { Pref r = Pref(e2);
763: Pname m = Pname(r->mem);
764: while (m->base == MDOT) m = Pname(m->mem);
765: if (m->n_stclass == STATIC) { // & static member
766: Pexpr x;
767: delp:
768: x = e2;
769: e2 = m;
770: r->mem = 0;
771: DEL(x);
772: }
773: else if (m->tp->base == FCT) { // & member fct
774: Pfct f = Pfct(m->tp);
775: if (f->f_virtual) { // &p->f ==> p->vtbl[fi].f
776: int index = f->f_virtual;
777: Pexpr ie = index ? new ival(index):0;
778: if (ie) ie->tp = int_type;
779: Pname cn = m->n_table->t_name;
780: Pname vp = find_vptr(Pclass(cn->tp));
781: r->mem = vp;
782:
783: if ( obase == MDOT ) {
784: base = DEREF;
785: e1 = e2;
786: e2 = ie;
787: }
788: else { // support old style &b.vf
789: base = MDOT;
790: mem = new expr(DEREF,e2,ie);
791: string2 = "f";
792: i1 = 9;
793: }
794: }
795: else {
796: goto delp;
797: }
798: }
799: break;
800: }
801: }
802: break;
803:
804: case ANDAND:
805: case OROR:
806: // error('d',"simpl::expr %k", base );
807: if ( Ntmp_dtor && need_lift_dtors(this)) {
808: need_lift = 1;
809: Pexpr e = lift_dtors(this, Ntmp_tbl);
810: *this = *e;
811: }
812: Ntmp = 0;
813: // no break
814:
815: default:
816: if (e1) e1->simpl();
817: if (e2) e2->simpl();
818: break;
819:
820: case CM:
821: case G_CM:
822: {
823: Pname n = 0;
824: e1->simpl();
825: e2->simpl();
826: if (e1->base==ICALL && e1->e1==0) n = e1->il->fct_name;
827: if (e2->base==ICALL && e2->e1==0) n = e2->il->fct_name;
828: if (n) error('s',"cannot expand inline void%n called in commaE",n);
829: // no break
830: }
831: case NAME:
832: case DUMMY:
833: case ICON:
834: case FCON:
835: case CCON:
836: case IVAL:
837: // case FVAL:
838: // case LVAL:
839: case STRING:
840: case ZERO:
841: case ILIST:
842: // case MDOT:
843: return;
844: /*
845: case SIZEOF:
846: base = IVAL;
847: i1 = tp2->tsizeof();
848: tp2 = 0; // can't DEL(tp2)
849: break;
850: */
851: case SIZEOF:
852: if (e1) e1->simpl();
853: return;
854:
855: case G_CALL:
856: case CALL:
857: Pcall(this)->simpl();
858: break;
859:
860: case NEW:
861: case GNEW:
862: simpl_new();
863: return;
864:
865: case DELETE:
866: case GDELETE:
867: simpl_delete();
868: break;
869:
870: case QUEST:
871: cond->simpl();
872: Ntmp = 0;
873: e2->simpl();
874: // no break
875:
876: case CAST:
877: case REF:
878: e1->simpl();
879: break;
880:
881: case DOT:
882: e1->simpl();
883: switch (e1->base) {
884: case CM:
885: case G_CM:
886: { // &( , name). => ( ... , &name)->
887: Pexpr ex = e1;
888: cfr:
889: switch (ex->e2->base) {
890: case NAME:
891: base = REF;
892: ex->e2 = ex->e2->address();
893: break;
894: case CM:
895: case G_CM:
896: ex = ex->e2;
897: goto cfr;
898: }
899: }
900: }
901: break;
902:
903: case ASSIGN:
904: {
905: Pfct f = 0;
906: Pexpr th = 0;
907: if ( curr_fct ) {
908: f = Pfct(curr_fct->tp);
909: th = f->f_this;
910: }
911:
912: imeasure++;
913: if (e1) e1->simpl();
914: if (e2) {
915: Pexpr c = e2;
916: c->simpl();
917: while (c->base == CAST) c = c->e1;
918: if (c->base == ILIST) e2 = c;
919:
920: if (e2->base == ILIST) { // pointer to member assignment
921: Pexpr ee = mptr_assign(e1,e2);
922: Pexpr eee = new expr(CM,ee->e2,e1);
923: e1 = ee->e1;
924: e2 = eee;
925: base = CM;
926: delete ee;
927: }
928: }
929:
930: if (th && th==e1 && curr_fct->n_oper==CTOR && init_list) {
931: // this=e2 => (this=e2,init_list)
932: Pclass cl = Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp);
933: if (cl->c_body == 1) cl->dcl_print(0);
934: imeasure++;
935: base = CM;
936: e1 = new expr(ASSIGN,e1,e2);
937: e2 = init_list;
938: if (warning_opt) // timid
939: error('w',"assignment to ``this'' inK: try defining%t::operator new() instead",f->memof);
940: }
941: break;
942: }
943: }
944:
945: switch (base) {
946: case QUEST:
947: case ANDAND:
948: case OROR:
949: if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,base);
950: // no break;
951: default:
952: Ntmp = 0;
953: }
954:
955: if (tp==int_type || tp==defa_type) {
956: Neval = 0;
957: no_sizeof = 1; // do not convert sizeof's to ints
958: long i = eval();
959: no_sizeof = 0;
960: if (Neval == 0) {
961: base = IVAL;
962: i1 = i;
963: }
964: }
965:
966: }
967:
968: Pexpr vptr_entry(Pexpr pp, Pexpr ie, Pclass cl)
969: {
970: Pptr ttemp = pp->tp->is_ptr_or_ref();
971:
972: if (ttemp) {
973: Ptype pt = ttemp->typ; // check if cast pp = (base*)pp
974: Pclass pc = Pclass(pt->is_cl_obj()->tp); // is needed
975: if (pc!=cl) pp = new cast(cl,pp);
976: }
977: Pname vp = find_vptr(cl);
978: if (vp == 0) {
979: if (cc->cot && cc->cot->in_class==cl)
980: error('s',"cannot inline virtual function call before class %s has been completely declared - try uninlining %n",cl->string,curr_fct);
981: else error('i',"can't find vptr");
982: }
983: Pexpr vptr = new ref(REF,pp,vp); // pp->vptr
984: return new expr(DEREF,vptr,ie); // pp->vptr[i]
985: }
986:
987: Pexpr new_this(Pexpr pp, Pexpr ee)
988: {
989: //error('d',"new this");
990: Pexpr dee = new mdot("d",ee); // pp->vptr[i].d
991: dee->i1 = 9;
992: Pexpr nthis = new cast(Pchar_type,pp);
993: nthis = new expr(PLUS,nthis,dee); // ((char*)pp)+delta
994: Ptype ct = pp->tp;
995: if (pp->base==NAME && Pname(pp)->n_xref) ct = pp->tp->addrof();
996: return new cast(ct,nthis);
997: }
998:
999: Pcall vcall(Pexpr pp, Pexpr ie, Pfct f, Pclass cl, Pexpr args)
1000: /*
1001: generate a call of the virtual function with the index ``ie''
1002: and type "f" in class ``cl'' for the object pointed to by ``pp''
1003:
1004: multiple inheritance virtual call:
1005:
1006: p->f(x) is resolved like this
1007: pp = p; // avoid side effects
1008: pp = p.base_object; // often: pp = p;
1009: // done when the name was resolved
1010: i = index(f);
1011: entry = pp->_vtbl[i-1];
1012: pp = (T*)(((char*)pp)+entry.d)
1013: (*(ftype)entry.f)(pp,x)
1014: */
1015: {
1016: //error('d',"vcall %t",cl);
1017: if (cl->c_body==1) cl->dcl_print(0); // look for first use of cl
1018:
1019: imeasure+=6;
1020: Pexpr ee = vptr_entry(pp,ie,cl);
1021:
1022: Pexpr fee = new mdot("f",ee);
1023: fee->i1 = 9;
1024: Ptype pft = f->addrof();
1025: fee = new cast(pft,fee); // (T)pp->vptr[i].f
1026: Pexpr r = new expr(DEREF,fee,0); // *(T)pp->vptr[i].f
1027: // e1->tp must be 0, means "argtype encoded"
1028: r->tp2 = Ptype(f->f_this); // encode argtype
1029:
1030: Pexpr nthis = new_this(pp,ee);
1031:
1032: args = new expr(ELIST,nthis,args);
1033: args->simpl();
1034:
1035: Pcall c = new call(r,args);
1036: c->tp = f->returns;
1037: return c;
1038: }
1039:
1040: void call::simpl()
1041: /*
1042: fix member function calls:
1043: p->f(x) becomes f(p,x)
1044: o.f(x) becomes f(&o,x)
1045: or if f is virtual:
1046: p->f(x) is resolved like this
1047: pp = p;
1048: i = index(f);
1049: entry = pp->_vtbl[i-1];
1050: pp = (T*)(((char*)pp)+entry.i)
1051: (*entry.f)(pp,x)
1052: replace calls to inline functions by the expanded code
1053: */
1054: {
1055: Pname fn = fct_name;
1056: //error('d',"%d call::simpl() fn %n %d e1 %d",this,fn,fn,e1);
1057: Pfct f = fn ? Pfct(fn->tp) : 0;
1058:
1059: if (fn == 0) e1->simpl();
1060:
1061: if (f) {
1062: switch(f->base) {
1063: case ANY:
1064: return;
1065: case OVERLOAD:
1066: fct_name = fn = Pgen(f)->fct_list->f;
1067: f = Pfct(fn->tp);
1068: }
1069: }
1070:
1071: switch (e1->base) {
1072: case MEMPTR: // (p ->* q)(args)
1073: {
1074: Pexpr p = e1->e1;
1075: Pexpr q = e1->e2;
1076: Pclass cl = Pclass(e1->tp2);
1077: Pfct f = Pfct(q->tp->deref());
1078:
1079: if (e2) e2->simpl();
1080:
1081: if (f->f_this == 0) { // might not know about ``this'' yet
1082: if (f->memof == 0) error('i',"memof missing");
1083: Pname tt = new name("this");
1084: tt->n_scope = ARG;
1085: tt->tp = f->memof->this_type;
1086: PERM(tt);
1087: // f->f_this = f->f_args = tt;
1088: tt->n_list = f->argtype;
1089: // f->f_this = tt;
1090: tt->n_list = f->f_result ? f->f_result : f->argtype;
1091: f->f_this = f->f_args = tt;
1092: }
1093: //error('d',"f_this %d",f->f_this);
1094: extern has_virt(Pclass);
1095:
1096: // beware of sideeffects:
1097: nin = 1;
1098: if (q->not_simple()) error('s',"2nd operand of .* too complicated");
1099: nin = 0;
1100:
1101: Pexpr qq = new mdot("f",q); // the function: (*(right type)q.f)
1102: qq->i1 = 9;
1103: qq = new cast(f->addrof(),qq);
1104: Pexpr nc = new expr(DEREF,qq,0);
1105: nc->tp2 = Ptype(f->f_this); // encode argtype
1106:
1107: Pexpr nthis = new_this(p,q); // arguments: (p+q.d,args)
1108: Pexpr args = new expr(ELIST,nthis,e2);
1109: imeasure+=3;
1110:
1111: if (has_virt(cl) == 0) { // no virtuals: simple
1112: if (cl->defined == 0)
1113: error("call throughP toMF before definition ofC %t",cl);
1114: //error('d',"no virt");
1115: // (p ->* q)(args) => (*q.f)(p+q.d,args)
1116: e1 = nc;
1117: e2 = args;
1118: return;
1119: }
1120:
1121: if (find_vptr(cl) == 0) { // must be a call to a second base
1122: // that we cannot handle yet
1123: // it is OK not to to generate
1124: // a virtual call since a
1125: // `sorry' will have been generated
1126: // at the point of initialization
1127: e1 = nc;
1128: e2 = args;
1129: return;
1130:
1131: }
1132: // beware of sideeffects:
1133: nin = 1;
1134: if (p->not_simple()) error('s',"1st operand of .* too complicated");
1135: nin = 0;
1136:
1137: Pexpr c = new mdot("i",q); // condition (q.i<0)
1138: c->i1 = 9;
1139: c = new expr(LT,c,zero);
1140:
1141: Pexpr ie = new mdot("i",q);
1142: ie->i1 = 9;
1143:
1144: base = QUEST;
1145: e1 = new call(nc,args);
1146: e2 = vcall(p,ie,f,cl,e2);
1147: cond = c;
1148: return;
1149: }
1150: case DOT:
1151: // if e1 is an object and not just a reference
1152: // the vtbl need not be used
1153: case REF:
1154: { Pref r = Pref(e1);
1155: Pexpr a1 = r->e1;
1156: int obj = r->n_initializer!=0; // if B::f don't use vcall
1157:
1158: if (obj == 0) { // don't use vcall if we have an object
1159: // (not a pointer or a reference)
1160: if (e1->base==DOT && a1->base!=DEREF) obj = 1;
1161: }
1162:
1163: //error('d',"fct_name %n f %d %d obj %d",fct_name,f,f->f_virtual,obj);
1164: if (f && obj==0 && f->f_virtual) {
1165: Pexpr a11 = 0;
1166:
1167: switch(a1->base) { // see if temporary might be needed
1168: case NAME:
1169: case MDOT:
1170: a11 = a1;
1171: break;
1172: case REF:
1173: case DOT:
1174: if (a1->e1->base==NAME
1175: || ((a1->e1->base==DOT || a1->e1->base==REF) && a1->e1->e1->base==NAME)) a11 = a1;
1176: break;
1177: case ADDROF:
1178: case G_ADDROF:
1179: if (a1->e2->base == NAME
1180: || ((a1->e2->base==DOT || a1->e2->base==REF) && a1->e2->e1->base==NAME)) a11 = a1;
1181: break;
1182: case CAST:
1183: switch (a1->e1->base) {
1184: case NAME:
1185: case MDOT:
1186: a11 = a1;
1187: }
1188: }
1189:
1190: // if( a1->base==REF && fn->n_oper==DTOR ){
1191: // a11 = a1;
1192: // goto zsw;
1193: // }
1194: //
1195: if (e1->base == DOT) {
1196: // zsw:
1197: if (a11) a11 = a11->address();
1198: a1 = a1->address();
1199: }
1200:
1201: if (a11 == 0) { // temporary (maybe) needed
1202: // e->f() => (t=e,t->f(t))
1203: if (a1->base==NAME)
1204: a11 = a1; // &*name has become name
1205: else {
1206: Pname nx = new name(make_name('K'));
1207: nx->tp = a1->tp;
1208: Pname n = nx->dcl(scope,ARG); // no init!
1209: delete nx;
1210: Pname cln = a1->tp->is_cl_obj();
1211: if (cln) {
1212: Pclass cl = Pclass(cln->tp);
1213: if (Ntmp==0 && cl->has_dtor()) Ntmp = cln;
1214: if (cl->has_itor()) n->n_xref = 1;
1215: }
1216: n->n_scope = FCT;
1217: n->assign();
1218: a11 = n;
1219: a1 = new expr(ASSIGN,n,a1);
1220: a1->tp = n->tp;
1221: a1->simpl();
1222: Pcall cc = new call(0,0);
1223: *cc = *this;
1224: base = CM;
1225: e1 = a1;
1226: e2 = cc;
1227: this = cc;
1228: }
1229: }
1230:
1231: int i = f->f_virtual;
1232: Pexpr ie = i?new ival(i):0; // index
1233: Pname cn = fn->n_table->t_name;
1234: if (fn
1235: && fn->n_initializer
1236: && cc->nof
1237: && cc->nof->n_oper==CTOR
1238: && Pfct(cc->nof->tp)->memof->c_abstract
1239: && strcmp(Pfct(cc->nof->tp)->memof->string, cn->string) == 0 ) {
1240: // permit x::x( x& xx ) { xx.pvf(); }
1241: Pexpr ee = e1->e1;
1242: while ( ee && ee->base != NAME ) ee = ee->e1;
1243: if ( ee && strcmp( ee->string, "this" )==0)
1244: error("call of pure virtualF%n inK%n",fn,cc->nof);
1245: }
1246: Pcall vc = vcall(a11,ie,f,Pclass(cn->tp),e2);
1247: *this = *vc;
1248: return;
1249: }
1250:
1251: Ptype tt = r->mem->tp;
1252: llp:
1253: //error('d',"llp %t",tt);
1254: switch (tt->base) {
1255: // default: // pointer to function: (n->ptr_mem)(args); do nothing
1256: case TYPE:
1257: tt = Pbase(tt)->b_name->tp;
1258: goto llp;
1259: case OVERLOAD: // n->fctmem(args);
1260: case FCT:
1261: if (fct_name==0) {
1262: // reconstitute fn destroyed to suppress "virtual"
1263: fct_name = fn = Pname(e1->n_initializer);
1264: f = Pfct(fn->tp);
1265: }
1266:
1267: if (e1->base == DOT) a1 = a1->address();
1268: e2 = new expr(ELIST,a1,e2);
1269: e1 = r->mem;
1270: }
1271: }
1272: }
1273:
1274: if (e2) e2->simpl();
1275: //error('d',"fn %n inl %d imes %d",fn,f->f_inline,f->f_imeasure);
1276: if (fn && f->f_inline && debug_opt==0) {
1277: imeasure += f->f_imeasure;
1278: Pclass cl = f->memof;
1279: if (cl && cl->c_body) cl->dcl_print(0);
1280: Ptable oscope = scope;
1281: Pexpr ee = f->expand(fn,scope,e2);
1282: scope = oscope;
1283: if (ee) *Pexpr(this) = *ee;
1284: }
1285: else if (fn && f->f_inline==0 && f->f_imeasure) {
1286: extern void uninline(Pname fn);
1287: uninline(fn);
1288: imeasure += 3;
1289: }
1290: else if (fn && debug_opt && f->f_inline==ITOR) {
1291: extern void expand_itor(Pclass);
1292: expand_itor(f->memof);
1293: }
1294: else
1295: imeasure += 3;
1296: }
1297:
1298: void uninline(Pname fn)
1299: // inline turned static
1300: {
1301: Pfct f = Pfct(fn->tp);
1302: //error('d',"uninline %n %d %d",fn,f->body,f->f_expr);
1303:
1304: if (warning_opt) {
1305: error('w',"%n too complex for inlining",fn);
1306: error('w',"out-of-line copy of %n created",fn);
1307: }
1308: f->f_imeasure = 0; // now it really is just static
1309:
1310: Pstmt s = f->body->s;
1311: // for (s = f->body->s; s; s=s->s_list)
1312: //error('d',"start %d %k",s->e,s->e->base);
1313: // s = f->body->s;
1314: while (s) {
1315: //error('d',"s %k %d %k",s->base,s->e,s->e->base);
1316: if (s->base == SM) {
1317: // turn comma expression into statement list
1318: Pexpr e = s->e;
1319: if (e)
1320: switch (e->base) {
1321: case CM:
1322: case G_CM:
1323: { Pstmt ss = new estmt(SM,no_where,e->e2,0);
1324: s->e = e->e1;
1325: ss->s_list = s->s_list;
1326: s->s_list = ss;
1327: delete e;
1328: continue;
1329: }
1330: }
1331: }
1332: s = s->s_list;
1333: }
1334: // for (s = f->body->s; s; s=s->s_list)
1335: //error('d',"echo %k %d %k",s->base,s->e,s->e->base);
1336:
1337: fn->dcl_print(0);
1338: }
1339:
1340: /*
1341: void ccheck(Pexpr e)
1342:
1343: Is there a conditional in this expression? (not perfect)
1344:
1345: {
1346: //error('d',"ccheck(e %k)",e,e?e->base,0);
1347: if (e)
1348: switch (e->base) {
1349: case QUEST:
1350: case ANDAND:
1351: case OROR:
1352: error('s',"E too complicated: uses%k and needs temporary ofCW destructor",e->base);
1353: break;
1354: case LT:
1355: case LE:
1356: case GT:
1357: case GE:
1358: case EQ:
1359: case NE:
1360: case ASSIGN:
1361: case ASPLUS:
1362: case ASMINUS:
1363: case G_CM:
1364: case CM:
1365: case PLUS:
1366: case MINUS:
1367: case MUL:
1368: case DIV:
1369: case OR:
1370: case ER:
1371: case AND:
1372: case G_CALL:
1373: case CALL:
1374: case ELIST:
1375: case DEREF:
1376: ccheck(e->e1);
1377: case NOT:
1378: case COMPL:
1379: case CAST:
1380: case ADDROF:
1381: case G_ADDROF:
1382: ccheck(e->e2);
1383: break;
1384: case ICALL: // check inlined arguments
1385: { Pin il = e->il;
1386: for (int i = 0; il->args[i].arg && i<il->i_slots; i++) ccheck(il->args[i].arg);
1387: }
1388: }
1389: }
1390: */
1391:
1392: void temp_in_cond(Pexpr ee, Pstmt ss, Ptable tbl)
1393: /*
1394: insert destructor calls 'ss' into condition 'ee'
1395: ee => (Qnn = ee, dtors, Qnn)
1396: */
1397: {
1398: //error('d',"temp_in_cond");
1399: // ccheck(ee);
1400: while (ee->base==CM || ee->base==G_CM) ee = ee->e2;
1401: Ptype ct = ee->tp;
1402: Pname n = new name(make_name('Q')); // int Qnn;
1403: n->tp = ct;
1404: Pname tmp = n->dcl(tbl,ARG);
1405: delete n;
1406: tmp->n_scope = FCT;
1407:
1408: Pexpr v = new expr(0,0,0);
1409: *v = *ee;
1410: PERM(ct);
1411: v = new cast(ct,v);
1412:
1413: tmp->n_assigned_to = 1;
1414: Pexpr c = new expr(ASSIGN,tmp,v); // Qnn = ee
1415: c->tp = ct;
1416: ee->base = CM;
1417: ee->e1 = c;
1418:
1419: Pexpr ex = 0; // add dtors at end
1420:
1421: for (Pstmt sx = ss; sx; sx = sx->s_list) {
1422: if (ex) {
1423: ex = new expr(CM,ex,sx->e);
1424: ex->tp = sx->e->tp;
1425: }
1426: else
1427: ex = sx->e;
1428: }
1429: ee->e2 = new expr(CM,ex,tmp); // add Qnn at end
1430: ee->e2->tp = ct;
1431: }
1432:
1433: bit not_safe(Pexpr e)
1434: {
1435:
1436: switch (e->base) {
1437: default:
1438: return 1;
1439: /*
1440: case CALL:
1441: case G_CALL:
1442: case DOT:
1443: case REF:
1444: case ANAME:
1445: return 1;
1446: */
1447: case NAME:
1448: // if the name is automatic and has a destructor it is not safe
1449: // to destroy it before returning an expression depending on it
1450: { Pname n = Pname(e);
1451: if (n->n_table!=gtbl && n->n_table->t_name==0) {
1452: Pname cn = n->tp->is_cl_obj();
1453: if (cn && Pclass(cn->tp)->has_dtor()) return 1;
1454: }
1455: }
1456: case IVAL:
1457: case ICON:
1458: case CCON:
1459: case FCON:
1460: case STRING:
1461: return 0;
1462: case NOT:
1463: case COMPL:
1464: case ADDROF:
1465: case G_ADDROF:
1466: return not_safe(e->e2);
1467: case DEREF:
1468: // return not_safe(e->e1) || e->e2?not_safe(e->e2):0;
1469: { int i = not_safe(e->e1);
1470: if (i) return i;
1471: if (e->e2) return not_safe(e->e2);
1472: return 0;
1473: }
1474: case CM:
1475: case PLUS:
1476: case MINUS:
1477: case MUL:
1478: case DIV:
1479: case MOD:
1480: case ASSIGN:
1481: case ASPLUS:
1482: case ASMINUS:
1483: case ASMUL:
1484: case ASDIV:
1485: case OR:
1486: case AND:
1487: case OROR:
1488: case ANDAND:
1489: case LT:
1490: case LE:
1491: case GT:
1492: case GE:
1493: case EQ:
1494: case NE:
1495: return not_safe(e->e1) || not_safe(e->e2);
1496: case QUEST:
1497: return not_safe(e->cond) || not_safe(e->e1) || not_safe(e->e2);
1498: }
1499: }
1500:
1501:
1502: Pexpr curr_expr; /* to protect against an inline being expanded twice
1503: in a simple expression keep track of expressions
1504: being simplified
1505: */
1506:
1507: Pstmt stmt::simpl()
1508: /*
1509: return a pointer to the last statement in the list, or 0
1510: */
1511: {
1512: if (this == 0) error('i',"0->S::simpl()");
1513: DB( if(Sdebug>=1){
1514: error('d',"%d->stmt::simpl(): %k",this,base);
1515: if(Sdebug>=2) display_stmt(this);
1516: });
1517: //Pstmt ostmt = Cstmt;
1518: //if ( where.line ) Cstmt = this;
1519:
1520: stmtno++;
1521: curr_expr = e;
1522: // need_lift = 0;
1523: Ntmp_tbl = base != BLOCK ? memtbl : 0;
1524: // error('d',"stmt::simpl %k s_list %d need_lift: %d",base,s_list,need_lift);
1525:
1526: switch (base) {
1527: default:
1528: error('i',"S::simpl(%k)",base);
1529:
1530: case ASM:
1531: break;
1532:
1533: case BREAK:
1534: if (break_del_list) { // break => { _dtor()s; break; }
1535: Pstmt bs = new stmt(base,where,0);
1536: Pstmt dl = break_del_list->copy();
1537: base = BLOCK;
1538: s = new pair(where,dl,bs);
1539: }
1540: break;
1541:
1542: case CONTINUE:
1543: if (continue_del_list) { // continue => { _dtor()s; continue; }
1544: Pstmt bs = new stmt(base,where,0);
1545: Pstmt dl = continue_del_list->copy();
1546: base = BLOCK;
1547: s = new pair(where,dl,bs);
1548: }
1549: break;
1550:
1551: case DEFAULT:
1552: s->simpl();
1553: break;
1554:
1555: case SM:
1556: if (e) {
1557: if (e->base == DEREF) e = e->e1;
1558: e->simpl();
1559: if (e->base == DEREF) e = e->e1;
1560: }
1561: break;
1562:
1563: case RETURN:
1564: { /* return x;
1565: =>
1566: { dtor()s; return x; }
1567: OR (returning an X where X(X&) is defined) =>
1568: { ctor(_result,x); _dtor()s; return; }
1569: OR (where x needs temporaries)
1570: OR (where x might involve an object to be destroyed) =>
1571: { _result = x; _dtor()s; return _result; }
1572: return; =>
1573: { _dtor()s; return; }
1574: OR (in constructors) =>
1575: { _dtor()s; return _this; }
1576: */
1577: Pstmt sx = this;
1578: Pexpr ex = e;
1579:
1580: no_of_returns++;
1581:
1582: Pstmt dl = (del_list) ? del_list->copy() : 0;
1583: Pfct f = Pfct(curr_fct->tp);
1584:
1585: if (e == 0) e = dummy;
1586: if (e==dummy && curr_fct->n_oper==CTOR) e = f->f_this;
1587:
1588:
1589: // need to generate a temporary for mptr return
1590: Pexpr tt = e;
1591: while ( tt->base == CAST )
1592: tt = tt->e1;
1593: if ( tt->base == ILIST )
1594: e = tt;
1595:
1596: if (e->base == ILIST) {
1597: extern Pbase mptr_type;
1598: extern Ptype Pvptr_type;
1599: Pexpr mptr_assign(Pexpr, Pexpr);
1600: // memptr constant
1601: // return({1,2,f}) ==> memptr t; return((t={1,2,f},&t))
1602:
1603: Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl;
1604: Pname temp = make_tmp('A',mptr_type,ftbl);
1605:
1606: // placed in mptr_assign()
1607: // temp->use(); // necessary for inlines to force declaration
1608:
1609: e = mptr_assign(temp,e);
1610: e = new expr(G_CM,e,temp);
1611: e->tp = mptr_type;
1612: }
1613:
1614: if (f->f_result) { // ctor(_result,x); dtors; return;
1615: if (e->base == G_CM) e = replace_temp(e,f->f_result);
1616: e->simpl();
1617: Pstmt cs = new estmt(SM,where,e,0);
1618: if (dl) cs = new pair(where,cs,dl);
1619: base = PAIR;
1620: s = cs;
1621: s2 = new estmt(RETURN,where,0,0);
1622: //#ifdef RETBUG
1623: // s2->empty = 1; // fudge to bypass C bug (see print.c)
1624: // s2->ret_tp = ret_tp;
1625: //#endif
1626: }
1627: else { // dtors; return e;
1628: e->simpl();
1629: if (dl) {
1630: if (e!=dummy && not_safe(e)) {
1631: // { _result = x; _dtor()s; return _result; }
1632: Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl;
1633:
1634: Pname r = ftbl->look("_result",0);
1635: if (r == 0) {
1636: r = new name("_result");
1637: r->tp = ret_tp;
1638: Pname rn = r->dcl(ftbl,ARG);
1639: rn->n_scope = FCT;
1640: rn->where = no_where;
1641: rn->assign();
1642: delete r;
1643: r = rn;
1644: }
1645: Pexpr as = new expr(ASSIGN,r,e);
1646: as->tp = ret_tp; // wrong if = overloaded, but then X(X&) ought to have been used
1647: Pstmt cs = new estmt(SM,where,as,0);
1648: cs = new pair(where,cs,dl);
1649: base = PAIR;
1650: s = cs;
1651: s2 = new estmt(RETURN,where,r,0);
1652: // s2->ret_tp = ret_tp;
1653: }
1654: else { // { _dtor()s; return x; }
1655: base = PAIR;
1656: s = dl;
1657: s2 = new estmt(RETURN,where,e,0);
1658: }
1659: s2->ret_tp = ret_tp;
1660: }
1661: }
1662:
1663: // if (sx->memtbl) {
1664: // int i;
1665: // for (Pname n=sx->memtbl->get_mem(i=1); n; n=sx->memtbl->get_mem(++i)) {
1666: // Pname cn = n->tp->is_cl_obj();
1667: // if (cn && Pclass(cn->tp)->has_dtor()) {
1668: // ccheck(ex);
1669: // break;
1670: // }
1671: // }
1672: // }
1673: break;
1674: }
1675:
1676: case WHILE:
1677: case DO:
1678: e->simpl();
1679: { Pstmt obl = break_del_list;
1680: Pstmt ocl = continue_del_list;
1681: break_del_list = 0;
1682: continue_del_list = 0;
1683: s->simpl();
1684: break_del_list = obl;
1685: continue_del_list = ocl;
1686: }
1687: break;
1688:
1689: case SWITCH:
1690: e->simpl();
1691: { Pstmt obl = break_del_list;
1692: break_del_list = 0;
1693: s->simpl();
1694: break_del_list = obl;
1695: }
1696: switch (s->base) {
1697: case SM:
1698: // permit switch (expr) ;
1699: if (s->e) goto df;
1700: case DEFAULT:
1701: case LABEL:
1702: case CASE:
1703: break;
1704: case BLOCK:
1705: if (s->s)
1706: switch (s->s->base) {
1707: case BREAK: // to cope with #define Case break; case
1708: case CASE:
1709: case LABEL:
1710: case DEFAULT:
1711: break;
1712: default:
1713: goto df;
1714: }
1715: break;
1716: default:
1717: df:
1718: error(&s->where,"S orIdE not reached: (case label missing?)");
1719: }
1720: break;
1721:
1722: case CASE:
1723: e->simpl();
1724: s->simpl();
1725: break;
1726:
1727: case LABEL:
1728: if (del_list) error('s',"label in blockW destructors");
1729: s->simpl();
1730: break;
1731:
1732: case GOTO:
1733: /* If the goto is going to a different (effective) scope,
1734: then it is necessary to activate all relevant destructors
1735: on the way out of nested scopes, and issue errors if there
1736: are any constructors on the way into the target.
1737:
1738: Only bother if the goto and label have different effective
1739: scopes. (If mem table of goto == mem table of label, then
1740: they're in the same scope for all practical purposes.
1741: */
1742: {
1743: Pname n = scope->look( d->string, LABEL );
1744: if (n == 0) error('i',&where,"label%n missing",d);
1745: if(n->n_realscope!=scope && n->n_assigned_to) {
1746:
1747: /* Find the root of the smallest subtree containing
1748: the path of the goto. This algorithm is quadratic
1749: only if the goto is to an inner or unrelated scope.
1750: */
1751:
1752: Ptable r = 0;
1753:
1754: for(Ptable q=n->n_realscope; q!=gtbl; q=q->next) {
1755: for( Ptable p = scope; p != gtbl; p = p->next ) {
1756: if( p==q ) {
1757: r = p; // found root of subtree!
1758: goto xyzzy;
1759: }
1760: }
1761: }
1762:
1763: xyzzy: if( r==0 ) error( 'i',&where,"finding root of subtree" );
1764:
1765: /* At this point, r = root of subtree, n->n_realscope
1766: * = mem table of label, and scope = mem table of goto. */
1767:
1768: /* Climb the tree from the label mem table to the table
1769: * preceding the root of the subtree, looking for
1770: * initializers and ctors. If the mem table "belongs"
1771: * to an unsimplified block(s), the n_initializer field
1772: * indicates presence of initializer, otherwise initializer
1773: * information is recorded in the init_stat field of
1774: * mem table. */
1775:
1776: for( Ptable p=n->n_realscope; p!=r; p=p->next )
1777: if( p->init_stat == 2 ) {
1778: error(&where,"goto%n pastDWIr",d);
1779: goto plugh; /* avoid multiple error msgs */
1780: }
1781: else if( p->init_stat == 0 ) {
1782: int i;
1783: for(Pname nn=p->get_mem(i=1);nn;nn=p->get_mem(++i))
1784: if(nn->n_initializer||nn->n_evaluated){
1785: error(&nn->where,"goto%n pastId%n",d,nn);
1786: goto plugh;
1787: }
1788: }
1789: plugh:
1790:
1791: /* Proceed in a similar manner from the point of the goto,
1792: * generating the code to activate dtors before the goto. */
1793: /* There is a bug in this code. If there are class objects
1794: * of the same name and type in (of course) different mem
1795: * tables on the path to the root of the subtree from the
1796: * goto, then the innermost object's dtor will be activated
1797: * more than once. */
1798:
1799: {
1800: Pstmt dd = 0, ddt = 0;
1801:
1802: for( Ptable p=scope; p!=r; p=p->next ) {
1803: int i;
1804: for(Pname n=p->get_mem(i=1);n;n=p->get_mem(++i)) {
1805: Pname cln;
1806: if (n->tp == 0) continue; /* label */
1807: int dtor=1;
1808: if (inllist) {
1809: for (Pname nl=inllist->head;nl;nl=nl->n_list)
1810: if (n==nl) dtor=0;
1811: }
1812:
1813: if ( cln=n->tp->is_cl_obj() ) {
1814: Pclass cl = (Pclass)cln->tp;
1815: Pname d = cl->has_dtor();
1816:
1817: if (d && dtor) { /* n->cl::~cl(0); */
1818: Pexpr dl = call_dtor(n,d,0,DOT,one);
1819: Pstmt dls = new estmt(SM,n->where,dl,0);
1820: if (dd)
1821: ddt->s_list = dls;
1822: else
1823: dd = dls;
1824: ddt = dls;
1825: }
1826:
1827: }
1828: else if (cl_obj_vec) {
1829: Pclass cl = (Pclass)cl_obj_vec->tp;
1830: // Pname c = cl->has_ictor();
1831: Pname d = cl->has_dtor();
1832:
1833: if (d && dtor) { // __vec_delete(vec,noe,sz,dtor,0);
1834: Pfct f = Pfct(d->tp);
1835: int i = 0;
1836: for (Pname nn = f->f_args->n_list;
1837: nn && nn->n_list; nn=nn->n_list) i++;
1838: Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i));
1839: Pstmt dls = new estmt(SM,n->where,a,0);
1840: if (dd)
1841: ddt->s_list = dls;
1842: else
1843: dd = dls;
1844: ddt = dls;
1845: }
1846: }
1847: } /* end mem table scan */
1848: } /* end dtor loop */
1849:
1850: /* "activate" the list of dtors obtained. */
1851:
1852: if( dd ) {
1853: dd->simpl();
1854: Pstmt bs = new stmt( base, where, 0 );
1855: *bs = *this;
1856: base = PAIR;
1857: s = dd;
1858: s2 = bs;
1859: }
1860: }
1861: } /* end special case for non-local goto */
1862: }
1863: break;
1864:
1865: case IF:
1866: e->simpl();
1867: s->simpl();
1868: if (else_stmt) else_stmt->simpl();
1869: break;
1870:
1871: case FOR: // "for (s;e;e2) s2; => "s; for(;e,e2) s2"
1872: if (for_init) for_init->simpl();
1873: if (e) {
1874: curr_expr = e;
1875: e->simpl();
1876: }
1877: if (e2) {
1878: curr_expr = e2;
1879: e2->simpl();
1880: if (e2->base==ICALL)
1881: if (e2->e1 == 0) error('s',"cannot expand inline void%n called in forE", e2->il->fct_name);
1882: }
1883: { Pstmt obl = break_del_list;
1884: Pstmt ocl = continue_del_list;
1885: break_del_list = 0;
1886: continue_del_list = 0;
1887: s->simpl();
1888: break_del_list = obl;
1889: continue_del_list = ocl;
1890: }
1891: break;
1892:
1893: case BLOCK:
1894: Pblock(this)->simpl();
1895: break;
1896:
1897: case PAIR:
1898: break;
1899: }
1900:
1901: /*if (s) s->simpl();*/
1902: // error('d',"base %k memtbl %d e %d",base,memtbl);
1903: if (base!=BLOCK && memtbl) {
1904: Pstmt t1 = (s_list) ? s_list->simpl() : 0;
1905: Pstmt tpx = t1 ? t1 : this;
1906:
1907: Pstmt ss = 0;
1908: Pname cln; // used for warnings
1909: int i;
1910: Pname tn = memtbl->get_mem(i=1);
1911: for (; tn; tn=memtbl->get_mem(++i)) {
1912: // error('d',"tn: %n need_lift: %d",tn,need_lift);
1913: if (cln = tn->tp->is_cl_obj()) {
1914: Pname d = Pclass(cln->tp)->has_dtor();
1915: if (d) { /* n->cl::~cl(0); */
1916: if (need_lift &&
1917: is_probably_temp(tn->string) &&
1918: tmp_tbl->look(tn->string,0))
1919: continue;
1920:
1921: Pexpr dl = call_dtor(tn,d,0,DOT,one);
1922: Pstmt dls = new estmt(SM,tn->where,dl,0);
1923: dls->s_list = ss;
1924: ss = dls;
1925: }
1926: }
1927: }
1928:
1929: if (ss) {
1930: Pstmt t2 = ss->simpl();
1931:
1932: switch (base) {
1933: case IF:
1934: case WHILE:
1935: case DO:
1936: case SWITCH:
1937: temp_in_cond(e,ss,memtbl);
1938: break;
1939:
1940: case PAIR: // can hide a return
1941: { Pstmt ts = s2;
1942: while (ts->base==PAIR) ts = ts->s2;
1943: if (ts->base == RETURN) { // sordid
1944: this = ts;
1945: goto retu;
1946: }
1947: goto def;
1948: }
1949: case RETURN:
1950: retu:
1951: {
1952: if (e == 0) {
1953: // return; dtors; => dtors; return;
1954: Pstmt rs = new estmt(RETURN,where,0,0);
1955: //rs->empty = empty; // BSD fudge
1956: rs->ret_tp = ret_tp;
1957: base = PAIR;
1958: s = ss;
1959: s2 = rs;
1960: //Cstmt = ostmt;
1961: return t1 ? t1 : rs;
1962: }
1963:
1964: Pname cln = e->tp->is_cl_obj();
1965: if (cln==0
1966: || Pclass(cln->tp)->has_oper(ASSIGN)==0) {
1967: // ... return e; dtors; =>
1968: // ... X r; ... r = e; dtors; return r;
1969: Pname rv = new name("_rresult"); // NOT "_result"
1970: rv->tp = ret_tp /* e->tp */;
1971: if (memtbl == 0) memtbl = new table(4,0,0);
1972: Pname n = rv->dcl(memtbl,ARG);
1973: n->where = no_where;
1974: n->n_scope = FCT;
1975: n->n_assigned_to = 1;
1976: delete rv;
1977: Pstmt rs = new estmt(RETURN,where,n,0);
1978: rs->ret_tp = ret_tp;
1979: base = SM;
1980: e = new expr(ASSIGN,n,e);
1981: e->tp = n->tp;
1982: Pstmt ps = new pair(where,ss,rs);
1983: ps->s_list = s_list;
1984: s_list = ps;
1985: //Cstmt = ostmt;
1986: return t1 ? t1 : rs;
1987: }
1988: }
1989:
1990: case FOR: // don't know which expression the temp comes from
1991: error('s',&where,"E in %kS needs temporary ofC%nW destructor",base,cln);
1992: break;
1993:
1994: case SM: // place dtors after all "converted" DCLs
1995: if (t1) {
1996: // ccheck(e);
1997: for (Pstmt ttt, tt=this;
1998: (ttt=tt->s_list) && ttt->base==SM;
1999: tt = ttt) ;
2000: t2->s_list = ttt;
2001: tt->s_list = ss;
2002: //Cstmt = ostmt;
2003: return t1!=tt ? t1 : t2;
2004: }
2005: default:
2006: def:
2007: // if (e) ccheck(e);
2008: if (t1) { // t1 == tail of statment list
2009: t2->s_list = s_list;
2010: s_list = ss;
2011: //Cstmt = ostmt;
2012: return t1;
2013: }
2014: s_list = ss;
2015: //Cstmt = ostmt;
2016: return t2;
2017: }
2018: }
2019: //Cstmt = ostmt;
2020: return (t1) ? t1 : this;
2021: }
2022:
2023: //Cstmt = ostmt;
2024: return (s_list) ? s_list->simpl() : this;
2025: }
2026:
2027: Pstmt stmt::copy()
2028: // now handles dtors in the expression of an IF stmt
2029: // not general!
2030: {
2031: Pstmt ns = new stmt(0,curloc,0);
2032:
2033: *ns = *this;
2034: if (s) ns->s = s->copy();
2035: if (s_list) ns->s_list = s_list->copy();
2036:
2037: switch (base) {
2038: case PAIR:
2039: ns->s2 = s2->copy();
2040: break;
2041: }
2042:
2043: return ns;
2044: }
2045:
2046: Pname overFound = 0;
2047:
2048: static Pexpr
2049: mk_new_with_args( Pexpr pe, Ptype tt, Pclass cl, Pexpr vec = 0 )
2050: { // allocate using operator new(sizeof(cl),args1)
2051: Pexpr p;
2052: Pexpr args = pe->e2;
2053:
2054: // Pexpr ce = new texpr(SIZEOF,tt,0);
2055: Pexpr ce;
2056: if (vec)
2057: ce = vec;
2058: else ce = new texpr(SIZEOF,tt,0);
2059:
2060: (void) tt->tsizeof();
2061: ce->tp = size_t_type;
2062: args = new expr(ELIST,ce,args);
2063: char* s = oper_name(NEW);
2064: Pname n = new name(s);
2065: if (pe->base == GNEW) // ::new
2066: p = gtbl->look(s,0);
2067: else
2068: p = find_name(n,cl,scope,CALL,curr_fct);
2069: p = new call(p,args);
2070: overFound=0; // set in call_fct
2071: (void) p->call_fct(cl->memtbl);
2072: if (overFound && overFound->n_scope != EXTERN)
2073: check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
2074: overFound=0;
2075: return p;
2076: }
2077:
2078: void expr::simpl_new()
2079: /*
2080: change NEW or GNEW node to CALL node
2081: */
2082: {
2083: Pname cln;
2084: Pname ctor;
2085: int sz = 1;
2086: // int esz;
2087: Pexpr var_expr = 0;
2088: Pexpr const_expr = 0;
2089: Ptype tt = tp2;
2090: Pexpr arg;
2091: Pexpr szof;
2092: Pname nf;
2093: Pexpr init = e1;
2094:
2095: if (init && init->base) init = 0; // only non-ctor init
2096: // error('d',"simpl_new %k e1 %k e2 %k init %k",base, e1?e1->base:0,e2?e2->base:0,init?init->base:0);
2097:
2098: if ((cln=tt->is_cl_obj()) && init == 0) {
2099: Pclass cl = Pclass(cln->tp);
2100: Pexpr p;
2101: ctor=cl->has_ctor();
2102: // error('d',"cl %t ctor %n",cl, ctor);
2103: if (e2 // placement
2104: || ctor==0 // no constructor
2105: || ctor->n_table!=cl->memtbl // inherited constructor???
2106: || (base==GNEW && cl->has_oper(NEW)) )
2107: p = mk_new_with_args( this, tt, cl ); // new(sizeof(cl),args1)
2108: else {
2109: p = zero; // 0->ctor(args)
2110: // check visibility anyway...
2111: (void)mk_new_with_args(this,tt,cl);
2112: }
2113:
2114: if (ctor) {
2115: Pexpr c = e1; // ctor call generated in expr::typ
2116: Ptype ttt = tp;
2117: c->e1->e1 = p; // p->ctor
2118: c->simpl();
2119: *this = *c;
2120: tp = ttt;
2121: delete c;
2122: }
2123: else { // (tp)new(args)
2124: base = CAST;
2125: tp2 = tp;
2126: e1 = p;
2127: e2 = 0;
2128: simpl();
2129: }
2130: return;
2131: } else if ( cln ) {
2132: Pclass cl = Pclass(cln->tp);
2133: // check visibility anyway...
2134: (void)mk_new_with_args(this,tt,cl);
2135: }
2136:
2137: Pclass covn = 0;
2138: if (cl_obj_vec) {
2139: covn = Pclass(cl_obj_vec->tp);
2140: ctor = covn->has_ictor();
2141: if (ctor == 0) {
2142: if (covn->has_ctor()) error("new %s[], no defaultK",covn->string);
2143: cl_obj_vec = 0;
2144: }
2145: }
2146:
2147: xxx:
2148: //error('d',"xxx %t",tt);
2149: switch (tt->base) {
2150: case TYPE:
2151: tt = Pbase(tt)->b_name->tp;
2152: goto xxx;
2153:
2154: default:
2155: (void) tt->tsizeof();
2156: szof = new texpr(SIZEOF,tt,0);
2157: szof->tp = uint_type;
2158: break;
2159:
2160: case VEC:
2161: { Pvec v = Pvec(tt);
2162: //error('d',"v %d %d",v->size,v->dim);
2163: if (v->size)
2164: sz *= v->size;
2165: else if (v->dim)
2166: var_expr = v->dim;
2167: else
2168: sz = 0;
2169: tt = v->typ;
2170: goto xxx;
2171: }
2172: }
2173:
2174: if (cl_obj_vec) { // _vec_new(0,no_of_elements,element_size,ctor)
2175: const_expr = new ival(sz);
2176: Pexpr noe = (var_expr) ? (sz!=1) ? new expr(MUL,const_expr,var_expr) : var_expr : const_expr;
2177: const_expr = szof;
2178: const_expr->tp = uint_type;
2179: base = CALL;
2180: arg = new expr(ELIST,ctor,0);
2181: /*ctor->take_addr();*/
2182: ctor->lval(ADDROF);
2183: Pexpr sub=0;
2184: if (e2 && e2->e1 &&
2185: e2->e1->tp)
2186: { // new(size_t, args)
2187: Pexpr vec_sz = new expr(MUL, noe, const_expr);
2188: sub = mk_new_with_args( this, tt, covn, vec_sz );
2189: }
2190: arg = new expr(ELIST,const_expr,arg);
2191: arg = new expr(ELIST,noe,arg);
2192: // arg = new expr(ELIST,e2?e2:zero,arg); // may be preallocated
2193: arg = new expr(ELIST,e2?(sub?sub:e2):zero,arg); // may be preallocated
2194: base = CAST;
2195: tp2 = tp;
2196: e1 = new expr(G_CALL,vec_new_fct,arg);
2197: e1->fct_name = vec_new_fct;
2198: e1->tp = Pfct(vec_new_fct->tp)->returns;
2199: simpl();
2200: return;
2201: }
2202:
2203: /* call _new(element_size*no_of_elements) */
2204: //error('d',"sz %d var %d",sz,var_expr);
2205: if (sz == 1)
2206: arg = (var_expr) ? new expr(MUL,szof,var_expr) : szof;
2207: else {
2208: const_expr = new ival(sz);
2209: const_expr->tp = uint_type;
2210: const_expr = new expr(MUL,const_expr,szof);
2211: const_expr->tp = uint_type;
2212: arg = (var_expr) ? new expr(MUL,const_expr,var_expr) : const_expr;
2213: }
2214:
2215: arg->tp = uint_type;
2216: base = CAST;
2217: tp2 = tp;
2218: arg = new expr(ELIST,arg,e2);
2219: nf = gtbl->look(oper_name(NEW),0); // always global,
2220: // all class object handled above
2221: e1 = new expr(G_CALL,nf,arg);
2222: (void) e1->call_fct(gtbl);
2223: simpl();
2224:
2225: if (init) { // alloc(sz) => (p=alloc(sz),*p=init,p);
2226: Pexpr p = init->e1;
2227: Pexpr ee = new expr(0,0,0);
2228: *ee = *this;
2229: ee = new expr(ASSIGN,p,ee); // ee: p = alloc(sz);
2230: init->base = ASSIGN;
2231: init->e1 = p->contents(); // init: *p = init_val
2232: ee = new expr(CM,ee,init);
2233: ee->simpl();
2234: base = CM;
2235: e1 = ee;
2236: e2 = p;
2237: }
2238: }
2239:
2240: void expr::simpl_delete()
2241: /*
2242: delete p => _delete(p);
2243: or cl::~cl(p,1);
2244: delete[s]p => _delete(p);
2245: or vec_del_fct(p,vec_sz,elem_sz,~cl,1);
2246: */
2247: {
2248: for (Ptype tt = e1->tp; tt->base==TYPE; tt=Pbase(tt)->b_name->tp);
2249: tt = Pptr(tt)->typ;
2250: //error('d',"simpl_delete() %t",e1->tp);
2251: Pname cln = tt->is_cl_obj();
2252: Pname n;
2253: Pclass cl;
2254:
2255: if (cln) {
2256: cl = Pclass(cln->tp);
2257: if ((cl->defined&DEFINED) == 0) error('w',"delete%t (%t not defined)",cl,cl);
2258: }
2259: else
2260: cl = 0;
2261:
2262: if (cl && (n=cl->has_dtor())) { // ~cl() might be virtual
2263: //xxx check for private/protected op delete
2264: {
2265: Pexpr ee = new expr(ELIST,e1,0);
2266: char* s = oper_name(DELETE);
2267: Pname n;
2268: //error('d',"%s( %k )",s,e1->base);
2269: if (base!=GDELETE) {
2270: n = new name(s);
2271: n = (Pname)find_name(n,cl,scope,CALL,curr_fct);
2272: //error('d',"found%n %t",n,n->tp);
2273: if (n->tp->base==OVERLOAD
2274: || Pfct(n->tp)->nargs==2) {
2275: Pexpr ss = new texpr(SIZEOF,cl,0);
2276: ss->tp = size_t_type;
2277: ee->e2 = new expr(ELIST,ss,0);
2278: }
2279: }
2280: else
2281: n = gtbl->look(s,0);
2282: //error('d',"found%n %t",n,n->tp);
2283: ee = new call(n,ee);
2284: ee->base = G_CALL;
2285: //error('d',"delete..."); display_expr(ee);
2286: // following commented out to avoid typ::checking problems
2287: //overFound=0; // set in call_fct
2288: //(void) ee->call_fct(cl->memtbl);
2289: //if (overFound && overFound->n_scope != EXTERN)
2290: //check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
2291: //overFound=0;
2292: }
2293:
2294: //if ( base!=GDELETE ) (void) cl->has_oper(DELETE);
2295:
2296: if(base==GDELETE && e2==0 || Pfct(n->tp)->f_virtual) { // may need temp
2297: nin=1;
2298: int needtemp = e1->not_simple();
2299: nin=0;
2300: if(needtemp) {
2301: // convert: delete [e2] e1
2302: // to: (T=e1), delete [e2] T
2303: // where T is a new temporary.
2304: Pname tnx = new name(make_name('K'));
2305: tnx->tp = e1->tp;
2306: Pname tn = tnx->dcl(scope,FCT);
2307: delete tnx;
2308: tn->assign();
2309: e1 = new expr(ASSIGN,tn,e1);
2310: e2 = new expr(base,tn,e2);
2311: base=CM;
2312:
2313: simpl();
2314: return;
2315: }
2316: }
2317: Pexpr r = e1;
2318:
2319: // handle delete p, where p has a private destructor
2320: if (n->n_scope != PUBLIC) check_visibility(n,0,cl,cc->ftbl,cc->nof);
2321: //error('d',"e2 %d %k",e2,base);
2322: if (e2 == 0) { // e1->cl::~cl(1)
2323: Pexpr ee = call_dtor(r,n,base==GDELETE?0:one,REF,one);
2324: if (Pfct(n->tp)->f_virtual) {
2325: if (ansi_opt) { // q?void:int would be an error
2326: ee = new expr(G_CM,ee,zero);
2327: ee->tp = zero_type;
2328: }
2329: ee = new expr(QUEST,ee,zero);
2330: ee->tp = ee->e1->tp;
2331: ee->cond = r;
2332: }
2333: if (base == GDELETE) {
2334: char* s = oper_name(DELETE);
2335: Pexpr p = gtbl->look(s,0);
2336: e2 = new call(p,new expr(ELIST,e1,0));
2337: base = CM;
2338: e1 = ee;
2339: }
2340: else {
2341: *this = *ee;
2342: delete ee;
2343: }
2344: simpl();
2345: return;
2346: }
2347: else { // del_cl_vec(e1,e2,elem_size,~cl,1);
2348: Pexpr sz = new texpr(SIZEOF,tt,0);
2349: (void)tt->tsizeof();
2350: Pfct f = Pfct(n->tp);
2351: int i = 0;
2352: Pname nn = f->f_args->n_list;
2353: for (; nn && nn->n_list; nn=nn->n_list) i++;
2354: //error('d',"n %n i %d",n,i);
2355: Pexpr arg = new ival(i);
2356: sz->tp = uint_type;
2357: // Pexpr arg = one;
2358: arg = new expr(ELIST,one,arg);
2359: if (Pfct(n->tp)->f_virtual) {
2360: Pexpr a = new ref(REF,e1,n);
2361: a = a->address();
2362: a = new mdot( "f", a );
2363: a->i1 = 9;
2364: arg = new expr(ELIST,a,arg);
2365: }
2366: else {
2367: arg = new expr(ELIST,n,arg);
2368: n->lval(ADDROF); // n->take_addr();
2369: }
2370:
2371: arg = new expr(ELIST,sz,arg);
2372: if (e2->base==DUMMY) {
2373: e2 = new ival(-1); // handle `delete[]p'
2374: }
2375:
2376: arg = new expr(ELIST,e2,arg);
2377: arg = new expr(ELIST,e1,arg);
2378: Pexpr ee = new expr(G_CALL,vec_del_fct,arg);
2379: ee->fct_name = vec_del_fct;
2380: ee->tp = tp;
2381: // if (ansi_opt) { // q?void:int would be an error
2382: // ee = new expr(G_CM,ee,zero);
2383: // ee->tp = zero_type;
2384: // }
2385: // ee = new expr(QUEST,ee,zero);
2386: // ee->tp = tp;
2387: // ee->cond = r;
2388: *this = *ee;
2389: simpl();
2390: return;
2391: }
2392: }
2393: else if (cl_obj_vec) {
2394: error("delete array of arrays");
2395: }
2396: else { // _delete(e1)
2397: Pexpr ee = new expr(ELIST,e1,0);
2398: char* s = oper_name(DELETE);
2399: if (cl && base!=GDELETE) {
2400: Pname n = new name(s);
2401: e1 = find_name(n,cl,scope,CALL,curr_fct);
2402: if (e1->tp->base==OVERLOAD || Pfct(e1->tp)->nargs==2) {
2403: Pexpr ss = new texpr(SIZEOF,cl,0);
2404: ss->tp = size_t_type;
2405: ee->e2 = new expr(ELIST,ss,0);
2406: }
2407: }
2408: else
2409: e1 = gtbl->look(s,0);
2410: base = G_CALL;
2411: e2 = ee;
2412: overFound=0; // set in call_fct
2413: (void) call_fct(scope);
2414: if (overFound && overFound->n_scope != EXTERN)
2415: check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
2416: overFound=0;
2417: }
2418:
2419: Pcall(this)->simpl();
2420: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.