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