|
|
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:
204: if (own_tbl == 0) {
205: ss = (s) ? s->simpl() : 0;
206: return ss;
207: }
208:
209: scope = memtbl;
210: if (scope->init_stat == 0) scope->init_stat = 1; /* table is simplified. */
211:
212: for (n=scope->get_mem(i=1); n; n=scope->get_mem(++i)) {
213: Pstmt st = 0;
214: Pname cln;
215: Pexpr in = n->n_initializer;
216: //error('d',"local %k %n in %k %t",n->n_sto,n,in?in->base:0,in?in->tp:0);
217: if (in) {
218: scope->init_stat = 2; /* initializer in this scope */
219: if (n->n_sto == EXTERN) {
220: error(&n->where,"Id local extern%n",n);
221: continue;
222: }
223: }
224:
225: switch (n->n_scope) {
226: case ARG:
227: case 0:
228: case PUBLIC:
229: continue;
230: }
231:
232: if (n->n_stclass == STATIC) {
233: // local static class object
234: // error('d', "block::simpl: n %n in %t", n, in );
235: if (in && in->base==STAT_INIT) {
236: // dynamic initialization
237: // introduce first time switch
238: Pname cn;
239: Pname x;
240: Ptype ct;
241: if ( cn = n->tp->is_cl_obj() ) {
242: // error( 'd', "block::simpl: cl_obj_vec: %t", cl_obj_vec );
243: ct = new ptr(PTR,n->tp);
244: x = make_tmp('F', ct, gtbl );
245: x->n_initializer = zero;
246: }
247: else
248: x = make_tmp('F',int_type,scope);
249:
250: x->n_sto = n->n_stclass = STATIC;
251: if (in->e2)
252: in->base = ASSIGN;
253: else
254: in = in->e1;
255:
256: Pexpr set;
257: if ( cn ) {
258: x->dcl_print(0);
259: Pclass cl = Pclass(cn->tp);
260: Pname dtor = cl->has_dtor();
261: if ( dtor ) {
262: Pexpr eee = new expr(DEREF, x, 0 );
263: Pexpr c = call_dtor(eee,dtor,0,DOT,one);
264: c->tp = any_type;
265: Pexpr cc = new expr( QUEST, c, zero );
266: cc->cond = x;
267: Pstmt dls = new estmt( SM, n->where, cc, 0 );
268: if ( st_dlist ) dls->s_list = st_dlist;
269: st_dlist = dls;
270: }
271:
272: Pexpr xe = new expr( G_ADDROF, 0, n );
273: set = new expr(ASSIGN,x,xe);
274: set->tp = ct;
275: }
276: else {
277: set = new expr(ASSIGN,x,one);
278: set->tp = int_type;
279: }
280: in = new expr(G_CM,in,set);
281: in = new expr(STAT_INIT,zero,in);
282: in->cond = x;
283: }
284: else
285: continue;
286: }
287:
288: if ( in ) {
289: if ((in->base == ILIST && in->e2 == 0) ||
290: (in->base == STRING && n->tp->base == VEC))
291: if (ansi_opt==0) {
292: error('s',&n->where,"initialization of automatic aggregate");
293: continue;
294: }
295: }
296:
297: if (n->tp == 0) continue; /* label */
298: if (n->n_evaluated) continue;
299:
300: /* construction and destruction of temporaries is handled locally */
301: { char* s = n->string;
302: register char c3 = s[4];
303: if (s[0]=='_' && s[1]=='_' && s[2]=='D' && isdigit(c3)) continue;
304: }
305:
306: if ( cln=n->tp->is_cl_obj() ) {
307: Pclass cl = Pclass(cln->tp);
308: Pname d = cl->has_dtor();
309:
310: if (d) { // n->cl.dtor(0);
311: // local static class object
312: // suppress dtor for local static class object
313: if ( n->n_stclass == STATIC
314: && in
315: && in->base==STAT_INIT )
316: goto stat_init;
317:
318: Pexpr dl = call_dtor(n,d,0,DOT,one);
319: // Pstmt dls = new estmt(SM,n->where,dl,0);
320: Pstmt dls = new estmt(SM,no_where,dl,0);
321: if (dd) {
322: dls->s_list = dd;
323: dd = dls;
324: }
325: else
326: ddt = dd = dls;
327: }
328:
329: // error('d',"%n: in %d",n,in?in->base:0);
330: if (in) {
331: switch (in->base) {
332: case DEREF: // *constructor?
333: if (in->e1->base == G_CALL) {
334: Pname fn = in->e1->fct_name;
335: if (fn==0 || fn->n_oper!=CTOR) goto ddd;
336: st = new estmt(SM,n->where,in->e1,0);
337: n->n_initializer = 0;
338: break;
339: }
340: goto ddd;
341: case STAT_INIT:
342: // locate static class object
343: stat_init:
344: // error('d', "block::simpl: case #1 stat_init : n: %n", n );
345: in->base = QUEST;
346: st = new estmt(SM,n->where,in,0);
347: n->n_initializer = 0;
348: break;
349: case G_CM:
350: st = new estmt(SM,n->where,in->e1,0);
351: n->n_initializer = 0;
352: break;
353: case ASSIGN: // assignment to "n"?
354: if (in->e1 == n) {
355: st = new estmt(SM,n->where,in,0);
356: n->n_initializer = 0;
357: break;
358: }
359: default:
360: goto ddd;
361: }
362: }
363: }
364: else if (cl_obj_vec) {
365: Pclass cl = Pclass(cl_obj_vec->tp);
366: Pname d = cl->has_dtor();
367: Pname c = cl->has_ictor();
368: // error('d',"vec %n: in %k c %n",n,in?in->base:0,c);
369: n->n_initializer = 0;
370:
371: if (c) { // _vec_new(vec,noe,sz,ctor);
372: if (in==0 || in->base==ILIST) {
373: Pexpr a = cdvec(vec_new_fct,n,cl,c,-1,0);
374: st = new estmt(SM,n->where,a,0);
375: }
376: else
377: st = new estmt(SM,n->where,in,0);
378: }
379:
380: if (d) { // __vec_delete(vec,noe,sz,dtor,0);
381: Pfct f = Pfct(d->tp);
382: int i = 0;
383: for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) i++;
384: //error('d',"d %n i %d",n,i);
385: Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i));
386: // Pstmt dls = new estmt(SM,n->where,a,0);
387: Pstmt dls = new estmt(SM,no_where,a,0);
388: if (dd) {
389: dls->s_list = dd;
390: dd = dls;
391: }
392: else
393: ddt = dd = dls;
394: }
395: }
396: else if (in) {
397: switch (in->base) {
398: case ILIST:
399: switch (n->n_scope) {
400: case FCT:
401: if (in->e2) { // pointer to member
402: Pexpr ee = mptr_assign(n,in);
403: st = new estmt(SM,n->where,ee,0);
404: n->n_initializer = 0;
405: break;
406: }
407: case ARG:
408: if (ansi_opt == 0) error('s',"Ir list for localV%n",n);
409: }
410: break;
411: case STAT_INIT:
412: // error('d', "block::simpl: case #2 stat_init : n: %n", n );
413: in->base = QUEST;
414: st = new estmt(SM,n->where,in,0);
415: n->n_initializer = 0;
416: break;
417: case STRING:
418: if (n->tp->base==VEC) break; /* BUG char vec only */
419: default:
420: ddd:
421: { Pexpr ee = new expr(ASSIGN,n,in);
422: st = new estmt(SM,n->where,ee,0);
423: n->n_initializer = 0;
424: }
425: }
426: }
427:
428: if (st) {
429: if (ss)
430: sst->s_list = st;
431: else
432: ss = st;
433: sst = st;
434: }
435: }
436:
437: if (dd) {
438: Pstmt od = del_list;
439: Pstmt obd = break_del_list;
440: Pstmt ocd = continue_del_list;
441:
442: dd->simpl();
443: del_list = (od) ? Pstmt(new pair(curloc,dd,od)) : dd;
444: break_del_list = (break_del_list&&obd) ? Pstmt(new pair(curloc,dd,obd)) : dd;
445: continue_del_list = (continue_del_list&&ocd) ? Pstmt(new pair(curloc,dd,ocd)) : dd;
446:
447: stail = s ? s->simpl() : 0;
448:
449: Pfct f = Pfct(curr_fct->tp);
450: if (this!=f->body
451: || f->returns->base==VOID
452: || (f->returns->base!=VOID && no_of_returns==0 ) // you have been warned!
453: || strcmp(curr_fct->string,"main")==0 ) {
454: // not dropping through the bottom of a value returning function
455: if (stail) {
456: Pstmt tt = (stail->base==RETURN || stail->base==LABEL) ? stail : trim_tail(stail);
457: if (tt->base != RETURN) stail->s_list = dd;
458: }
459: else
460: s = dd;
461: stail = ddt;
462: }
463:
464: del_list = od;
465: continue_del_list = ocd;
466: break_del_list = obd;
467: }
468: else
469: stail = s ? s->simpl() : 0;
470:
471: if (ss) { /* place constructor calls */
472: ss->simpl();
473: sst->s_list = s;
474: s = ss;
475: if (stail == 0) stail = sst;
476: }
477:
478: scope = old_scope;
479:
480: return stail;
481: }
482:
483: int no_sizeof;
484:
485: void expr::simpl()
486: {
487: //error('d',"%d->expr::simpl %k e1=%d e2=%d",this,base,e1,e2);
488: if (this==0 || permanent==2) return; // already expanded
489:
490: switch (base) {
491: case MDOT:
492: mem->simpl();
493: // no break
494:
495: case ICALL: // already expanded
496: return;
497:
498: case G_ADDROF:
499: case ADDROF:
500: //error('d',"simpl & %k",e2->base);
501:
502: e2->simpl();
503: switch (e2->base) {
504: case DOT:
505: case REF:
506: { Pref r = Pref(e2);
507: Pname m = Pname(r->mem);
508: while (m->base == MDOT) m = Pname(m->mem);
509: if (m->n_stclass == STATIC) { // & static member
510: Pexpr x;
511: delp:
512: x = e2;
513: e2 = m;
514: r->mem = 0;
515: DEL(x);
516: }
517: else if (m->tp->base == FCT) { // & member fct
518: Pfct f = Pfct(m->tp);
519: if (f->f_virtual) { // &p->f ==> p->vtbl[fi]
520: int index = f->f_virtual;
521: Pexpr ie = index ? new ival(index):0;
522: if (ie) ie->tp = int_type;
523: Pname cn = m->n_table->t_name;
524: Pname vp = find_vptr(Pclass(cn->tp));
525: r->mem = vp;
526: base = DEREF;
527: e1 = e2;
528: e2 = ie;
529: }
530: else {
531: goto delp;
532: }
533: }
534: break;
535: }
536: }
537: break;
538:
539: case ANDAND:
540: case OROR:
541: Ntmp = 0;
542: // no break
543:
544: default:
545: if (e1) e1->simpl();
546: if (e2) e2->simpl();
547: break;
548:
549: case CM:
550: case G_CM:
551: { Pname n = 0;
552: e1->simpl();
553: e2->simpl();
554: if (e1->base==ICALL && e1->e1==0) n = e1->il->fct_name;
555: if (e2->base==ICALL && e2->e1==0) n = e2->il->fct_name;
556: if (n) error('s',"call of inline void%n in commaE",n);
557: // no break
558: }
559: case NAME:
560: case DUMMY:
561: case ICON:
562: case FCON:
563: case CCON:
564: case IVAL:
565: case FVAL:
566: case LVAL:
567: case STRING:
568: case ZERO:
569: case ILIST:
570: // case MDOT:
571: return;
572: /*
573: case SIZEOF:
574: base = IVAL;
575: i1 = tp2->tsizeof();
576: tp2 = 0; // can't DEL(tp2)
577: break;
578: */
579: case SIZEOF:
580: if (e1) e1->simpl();
581: return;
582:
583: case G_CALL:
584: case CALL:
585: Pcall(this)->simpl();
586: break;
587:
588: case NEW:
589: case GNEW:
590: simpl_new();
591: return;
592:
593: case DELETE:
594: case GDELETE:
595: simpl_delete();
596: break;
597:
598: case QUEST:
599: cond->simpl();
600: Ntmp = 0;
601: e2->simpl();
602: // no break
603:
604: case CAST:
605: case REF:
606: e1->simpl();
607: break;
608:
609: case DOT:
610: e1->simpl();
611: switch (e1->base) {
612: case CM:
613: case G_CM:
614: { // &( , name). => ( ... , &name)->
615: Pexpr ex = e1;
616: cfr:
617: switch (ex->e2->base) {
618: case NAME:
619: base = REF;
620: ex->e2 = ex->e2->address();
621: break;
622: case CM:
623: case G_CM:
624: ex = ex->e2;
625: goto cfr;
626: }
627: }
628: }
629: break;
630:
631: case ASSIGN:
632: {
633: Pfct f = 0;
634: Pexpr th = 0;
635: if ( curr_fct ) {
636: f = Pfct(curr_fct->tp);
637: th = f->f_this;
638: }
639:
640: imeasure++;
641: if (e1) e1->simpl();
642: if (e2) {
643: Pexpr c = e2;
644: c->simpl();
645: while (c->base == CAST) c = c->e1;
646: if (c->base == ILIST) e2 = c;
647:
648: if (e2->base == ILIST) { // pointer to member assignment
649: Pexpr ee = mptr_assign(e1,e2);
650: Pexpr eee = new expr(CM,ee->e2,e1);
651: e1 = ee->e1;
652: e2 = eee;
653: base = CM;
654: delete ee;
655: }
656: }
657:
658: if (th && th==e1 && curr_fct->n_oper==CTOR && init_list) {
659: // this=e2 => (this=e2,init_list)
660: Pclass cl = Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp);
661: if (cl->c_body == 1) cl->dcl_print(0);
662: imeasure++;
663: base = CM;
664: e1 = new expr(ASSIGN,e1,e2);
665: e2 = init_list;
666: if (warning_opt) // timid
667: error('w',"assignment to ``this'' inK: try defining%t::operator new() instead",f->memof);
668: }
669: break;
670: }
671: }
672:
673: switch (base) {
674: case QUEST:
675: case ANDAND:
676: case OROR:
677: if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,base);
678: // no break;
679: default:
680: Ntmp = 0;
681: }
682:
683: if (tp==int_type || tp==defa_type) {
684: Neval = 0;
685: no_sizeof = 1; // do not convert sizeof's to ints
686: long i = eval();
687: no_sizeof = 0;
688: if (Neval == 0) {
689: base = IVAL;
690: i1 = i;
691: }
692: }
693:
694: }
695:
696: Pexpr vptr_entry(Pexpr pp, Pexpr ie, Pclass cl)
697: {
698: Pptr ttemp = pp->tp->is_ptr_or_ref();
699:
700: if (ttemp) {
701: Ptype pt = ttemp->typ; // check if cast pp = (base*)pp
702: Pclass pc = Pclass(pt->is_cl_obj()->tp); // is needed
703: if (pc!=cl) pp = new cast(cl,pp);
704: }
705: Pname vp = find_vptr(cl);
706: if (vp == 0) error('i',"can't find vptr");
707: Pexpr vptr = new ref(REF,pp,vp); // pp->vptr
708: return new expr(DEREF,vptr,ie); // pp->vptr[i]
709: }
710:
711: Pexpr new_this(Pexpr pp, Pexpr ee)
712: {
713: //error('d',"new this");
714: Pexpr dee = new mdot("d",ee); // pp->vptr[i].d
715: dee->i1 = 9;
716: Pexpr nthis = new cast(Pchar_type,pp);
717: nthis = new expr(PLUS,nthis,dee); // ((char*)pp)+delta
718: Ptype ct = pp->tp;
719: if (pp->base==NAME && Pname(pp)->n_xref) ct = pp->tp->addrof();
720: return new cast(ct,nthis);
721: }
722:
723: Pcall vcall(Pexpr pp, Pexpr ie, Pfct f, Pclass cl, Pexpr args)
724: /*
725: generate a call of the virtual function with the index ``ie''
726: and type "f" in class ``cl'' for the object pointed to by ``pp''
727:
728: multiple inheritance virtual call:
729:
730: p->f(x) is resolved like this
731: pp = p; // avoid side effects
732: pp = p.base_object; // often: pp = p;
733: // done when the name was resolved
734: i = index(f);
735: entry = pp->_vtbl[i-1];
736: pp = (T*)(((char*)pp)+entry.d)
737: (*(ftype)entry.f)(pp,x)
738: */
739: {
740: //error('d',"vcall %t",cl);
741: if (cl->c_body==1) cl->dcl_print(0); // look for first use of cl
742:
743: imeasure+=6;
744: Pexpr ee = vptr_entry(pp,ie,cl);
745:
746: Pexpr fee = new mdot("f",ee);
747: fee->i1 = 9;
748: Ptype pft = f->addrof();
749: fee = new cast(pft,fee); // (T)pp->vptr[i].f
750: Pexpr r = new expr(DEREF,fee,0); // *(T)pp->vptr[i].f
751: // e1->tp must be 0, means "argtype encoded"
752: r->tp2 = Ptype(f->f_this); // encode argtype
753:
754: Pexpr nthis = new_this(pp,ee);
755:
756: args = new expr(ELIST,nthis,args);
757: args->simpl();
758:
759: Pcall c = new call(r,args);
760: c->tp = f->returns;
761: return c;
762: }
763:
764: void call::simpl()
765: /*
766: fix member function calls:
767: p->f(x) becomes f(p,x)
768: o.f(x) becomes f(&o,x)
769: or if f is virtual:
770: p->f(x) is resolved like this
771: pp = p;
772: i = index(f);
773: entry = pp->_vtbl[i-1];
774: pp = (T*)(((char*)pp)+entry.i)
775: (*entry.f)(pp,x)
776: replace calls to inline functions by the expanded code
777: */
778: {
779: Pname fn = fct_name;
780: //error('d',"%d call::simpl() fn %n %d e1 %d",this,fn,fn,e1);
781: Pfct f = fn ? Pfct(fn->tp) : 0;
782:
783: if (fn == 0) e1->simpl();
784:
785: if (f) {
786: switch(f->base) {
787: case ANY:
788: return;
789: case OVERLOAD:
790: fct_name = fn = Pgen(f)->fct_list->f;
791: f = Pfct(fn->tp);
792: }
793: }
794:
795: switch (e1->base) {
796: case MEMPTR: // (p ->* q)(args)
797: {
798: Pexpr p = e1->e1;
799: Pexpr q = e1->e2;
800: Pclass cl = Pclass(e1->tp2);
801: Pfct f = Pfct(q->tp->deref());
802:
803: if (e2) e2->simpl();
804:
805: if (f->f_this == 0) { // might not know about ``this'' yet
806: if (f->memof == 0) error('i',"memof missing");
807: Pname tt = new name("this");
808: tt->n_scope = ARG;
809: tt->tp = f->memof->this_type;
810: PERM(tt);
811: // f->f_this = f->f_args = tt;
812: tt->n_list = f->argtype;
813: // f->f_this = tt;
814: tt->n_list = f->f_result ? f->f_result : f->argtype;
815: f->f_this = f->f_args = tt;
816: }
817: //error('d',"f_this %d",f->f_this);
818: extern has_virt(Pclass);
819:
820: // beware of sideeffects:
821: extern nin;
822: nin = 1;
823: if (q->not_simple()) error('s',"2nd operand of .* too complicated");
824: nin = 0;
825:
826: Pexpr qq = new mdot("f",q); // the function: (*(right type)q.f)
827: qq->i1 = 9;
828: qq = new cast(f->addrof(),qq);
829: Pexpr nc = new expr(DEREF,qq,0);
830: nc->tp2 = Ptype(f->f_this); // encode argtype
831:
832: Pexpr nthis = new_this(p,q); // arguments: (p+q.d,args)
833: Pexpr args = new expr(ELIST,nthis,e2);
834: imeasure+=3;
835:
836: if (has_virt(cl) == 0) { // no virtuals: simple
837: if (cl->defined == 0)
838: error("call throughP toMF before definition ofC %t",cl);
839: //error('d',"no virt");
840: // (p ->* q)(args) => (*q.f)(p+q.d,args)
841: e1 = nc;
842: e2 = args;
843: return;
844: }
845:
846: if (find_vptr(cl) == 0) { // must be a call to a second base
847: // that we cannot handle yet
848: // it is OK not to to generate
849: // a virtual call since a
850: // `sorry' will have been generated
851: // at the point of initialization
852: e1 = nc;
853: e2 = args;
854: return;
855:
856: }
857: // beware of sideeffects:
858: nin = 1;
859: if (p->not_simple()) error('s',"1st operand of .* too complicated");
860: nin = 0;
861:
862: Pexpr c = new mdot("i",q); // condition (q.i<0)
863: c->i1 = 9;
864: c = new expr(LT,c,zero);
865:
866: Pexpr ie = new mdot("i",q);
867: ie->i1 = 9;
868:
869: base = QUEST;
870: e1 = new call(nc,args);
871: e2 = vcall(p,ie,f,cl,e2);
872: cond = c;
873: return;
874: }
875: case DOT:
876: // if e1 is an object and not just a reference
877: // the vtbl need not be used
878: case REF:
879: { Pref r = Pref(e1);
880: Pexpr a1 = r->e1;
881: int obj = r->n_initializer!=0; // if B::f don't use vcall
882:
883: if (obj == 0) { // don't use vcall if we have an object
884: // (not a pointer or a reference)
885: if (e1->base==DOT && a1->base!=DEREF) obj = 1;
886: }
887:
888: //error('d',"fct_name %n f %d %d obj %d",fct_name,f,f->f_virtual,obj);
889: if (f && obj==0 && f->f_virtual) {
890: Pexpr a11 = 0;
891:
892: switch(a1->base) { // see if temporary might be needed
893: case NAME:
894: case MDOT:
895: a11 = a1;
896: break;
897: case REF:
898: case DOT:
899: if (a1->e1->base==NAME
900: || ((a1->e1->base==DOT || a1->e1->base==REF) && a1->e1->e1->base==NAME)) a11 = a1;
901: break;
902: case ADDROF:
903: case G_ADDROF:
904: if (a1->e2->base == NAME
905: || ((a1->e2->base==DOT || a1->e2->base==REF) && a1->e2->e1->base==NAME)) a11 = a1;
906: break;
907: case CAST:
908: switch (a1->e1->base) {
909: case NAME:
910: case MDOT:
911: a11 = a1;
912: }
913: }
914:
915: // if( a1->base==REF && fn->n_oper==DTOR ){
916: // a11 = a1;
917: // goto zsw;
918: // }
919: //
920: if (e1->base == DOT) {
921: // zsw:
922: if (a11) a11 = a11->address();
923: a1 = a1->address();
924: }
925:
926: if (a11 == 0) { // temporary (maybe) needed
927: // e->f() => (t=e,t->f(t))
928: if (a1->base==NAME)
929: a11 = a1; // &*name has become name
930: else {
931: Pname nx = new name(make_name('K'));
932: nx->tp = a1->tp;
933: Pname n = nx->dcl(scope,ARG); // no init!
934: delete nx;
935: Pname cln = a1->tp->is_cl_obj();
936: if (cln) {
937: Pclass cl = Pclass(cln->tp);
938: if (Ntmp==0 && cl->has_dtor()) Ntmp = cln;
939: if (cl->has_itor()) n->n_xref = 1;
940: }
941: n->n_scope = FCT;
942: n->assign();
943: a11 = n;
944: a1 = new expr(ASSIGN,n,a1);
945: a1->tp = n->tp;
946: a1->simpl();
947: Pcall cc = new call(0,0);
948: *cc = *this;
949: base = CM;
950: e1 = a1;
951: e2 = cc;
952: this = cc;
953: }
954: }
955:
956: int i = f->f_virtual;
957: Pexpr ie = i?new ival(i):0; // index
958: Pname cn = fn->n_table->t_name;
959: if (fn
960: && fn->n_initializer
961: && cc->nof
962: && cc->nof->n_oper==CTOR
963: && Pfct(cc->nof->tp)->memof->c_abstract)
964: error("call of pure virtualF%n inK%n",fn,cc->nof);
965: Pcall vc = vcall(a11,ie,f,Pclass(cn->tp),e2);
966: *this = *vc;
967: return;
968: }
969:
970: Ptype tt = r->mem->tp;
971: llp:
972: //error('d',"llp %t",tt);
973: switch (tt->base) {
974: // default: // pointer to function: (n->ptr_mem)(args); do nothing
975: case TYPE:
976: tt = Pbase(tt)->b_name->tp;
977: goto llp;
978: case OVERLOAD: // n->fctmem(args);
979: case FCT:
980: if (fct_name==0) {
981: // reconstitute fn destroyed to suppress "virtual"
982: fct_name = fn = Pname(e1->n_initializer);
983: f = Pfct(fn->tp);
984: }
985:
986: if (e1->base == DOT) a1 = a1->address();
987: e2 = new expr(ELIST,a1,e2);
988: e1 = r->mem;
989: }
990: }
991: }
992:
993: if (e2) e2->simpl();
994: //error('d',"fn %n inl %d imes %d",fn,f->f_inline,f->f_imeasure);
995: if (fn && f->f_inline && debug_opt==0) {
996: imeasure += f->f_imeasure;
997: Pclass cl = f->memof;
998: if (cl && cl->c_body) cl->dcl_print(0);
999: Ptable oscope = scope;
1000: Pexpr ee = f->expand(fn,scope,e2);
1001: scope = oscope;
1002: if (ee) *Pexpr(this) = *ee;
1003: }
1004: else if (fn && f->f_inline==0 && f->f_imeasure) {
1005: extern void uninline(Pname fn);
1006: uninline(fn);
1007: imeasure += 3;
1008: }
1009: else if (fn && debug_opt && f->f_inline==ITOR) {
1010: extern void expand_itor(Pclass);
1011: expand_itor(f->memof);
1012: }
1013: else
1014: imeasure += 3;
1015: }
1016:
1017: void uninline(Pname fn)
1018: // inline turned static
1019: {
1020: Pfct f = Pfct(fn->tp);
1021: //error('d',"uninline %n %d %d",fn,f->body,f->f_expr);
1022:
1023: if (warning_opt) error('w',"%n too complex for inlining",fn);
1024: f->f_imeasure = 0; // now it really is just static
1025:
1026: Pstmt s = f->body->s;
1027: // for (s = f->body->s; s; s=s->s_list)
1028: //error('d',"start %d %k",s->e,s->e->base);
1029: // s = f->body->s;
1030: while (s) {
1031: //error('d',"s %k %d %k",s->base,s->e,s->e->base);
1032: if (s->base == SM) {
1033: // turn comma expression into statement list
1034: Pexpr e = s->e;
1035: if (e)
1036: switch (e->base) {
1037: case CM:
1038: case G_CM:
1039: { Pstmt ss = new estmt(SM,no_where,e->e2,0);
1040: s->e = e->e1;
1041: ss->s_list = s->s_list;
1042: s->s_list = ss;
1043: delete e;
1044: continue;
1045: }
1046: }
1047: }
1048: s = s->s_list;
1049: }
1050: // for (s = f->body->s; s; s=s->s_list)
1051: //error('d',"echo %k %d %k",s->base,s->e,s->e->base);
1052:
1053: fn->dcl_print(0);
1054: }
1055:
1056: /*
1057: void ccheck(Pexpr e)
1058:
1059: Is there a conditional in this expression? (not perfect)
1060:
1061: {
1062: //error('d',"ccheck(e %k)",e,e?e->base,0);
1063: if (e)
1064: switch (e->base) {
1065: case QUEST:
1066: case ANDAND:
1067: case OROR:
1068: error('s',"E too complicated: uses%k and needs temporary ofCW destructor",e->base);
1069: break;
1070: case LT:
1071: case LE:
1072: case GT:
1073: case GE:
1074: case EQ:
1075: case NE:
1076: case ASSIGN:
1077: case ASPLUS:
1078: case ASMINUS:
1079: case G_CM:
1080: case CM:
1081: case PLUS:
1082: case MINUS:
1083: case MUL:
1084: case DIV:
1085: case OR:
1086: case ER:
1087: case AND:
1088: case G_CALL:
1089: case CALL:
1090: case ELIST:
1091: case DEREF:
1092: ccheck(e->e1);
1093: case NOT:
1094: case COMPL:
1095: case CAST:
1096: case ADDROF:
1097: case G_ADDROF:
1098: ccheck(e->e2);
1099: break;
1100: case ICALL: // check inlined arguments
1101: { Pin il = e->il;
1102: for (int i = 0; il->args[i].arg && i<il->i_slots; i++) ccheck(il->args[i].arg);
1103: }
1104: }
1105: }
1106: */
1107:
1108: void temp_in_cond(Pexpr ee, Pstmt ss, Ptable tbl)
1109: /*
1110: insert destructor calls 'ss' into condition 'ee'
1111: ee => (Qnn = ee, dtors, Qnn)
1112: */
1113: {
1114: //error('d',"temp_in_cond");
1115: // ccheck(ee);
1116: while (ee->base==CM || ee->base==G_CM) ee = ee->e2;
1117: Ptype ct = ee->tp;
1118: Pname n = new name(make_name('Q')); // int Qnn;
1119: n->tp = ct;
1120: Pname tmp = n->dcl(tbl,ARG);
1121: delete n;
1122: tmp->n_scope = FCT;
1123:
1124: Pexpr v = new expr(0,0,0);
1125: *v = *ee;
1126: PERM(ct);
1127: v = new cast(ct,v);
1128: Pexpr c = new expr(ASSIGN,tmp,v); // Qnn = ee
1129: c->tp = ct;
1130: ee->base = CM;
1131: ee->e1 = c;
1132:
1133: Pexpr ex = 0; // add dtors at end
1134:
1135: for (Pstmt sx = ss; sx; sx = sx->s_list) {
1136: if (ex) {
1137: ex = new expr(CM,ex,sx->e);
1138: ex->tp = sx->e->tp;
1139: }
1140: else
1141: ex = sx->e;
1142: }
1143: ee->e2 = new expr(CM,ex,tmp); // add Qnn at end
1144: ee->e2->tp = ct;
1145: }
1146:
1147: bit not_safe(Pexpr e)
1148: {
1149:
1150: switch (e->base) {
1151: default:
1152: return 1;
1153: /*
1154: case CALL:
1155: case G_CALL:
1156: case DOT:
1157: case REF:
1158: case ANAME:
1159: return 1;
1160: */
1161: case NAME:
1162: // if the name is automatic and has a destructor it is not safe
1163: // to destroy it before returning an expression depending on it
1164: { Pname n = Pname(e);
1165: if (n->n_table!=gtbl && n->n_table->t_name==0) {
1166: Pname cn = n->tp->is_cl_obj();
1167: if (cn && Pclass(cn->tp)->has_dtor()) return 1;
1168: }
1169: }
1170: case IVAL:
1171: case ICON:
1172: case CCON:
1173: case FCON:
1174: case STRING:
1175: return 0;
1176: case NOT:
1177: case COMPL:
1178: case ADDROF:
1179: case G_ADDROF:
1180: return not_safe(e->e2);
1181: case DEREF:
1182: // return not_safe(e->e1) || e->e2?not_safe(e->e2):0;
1183: { int i = not_safe(e->e1);
1184: if (i) return i;
1185: if (e->e2) return not_safe(e->e2);
1186: return 0;
1187: }
1188: case CM:
1189: case PLUS:
1190: case MINUS:
1191: case MUL:
1192: case DIV:
1193: case MOD:
1194: case ASSIGN:
1195: case ASPLUS:
1196: case ASMINUS:
1197: case ASMUL:
1198: case ASDIV:
1199: case OR:
1200: case AND:
1201: case OROR:
1202: case ANDAND:
1203: case LT:
1204: case LE:
1205: case GT:
1206: case GE:
1207: case EQ:
1208: case NE:
1209: return not_safe(e->e1) || not_safe(e->e2);
1210: case QUEST:
1211: return not_safe(e->cond) || not_safe(e->e1) || not_safe(e->e2);
1212: }
1213: }
1214:
1215:
1216: Pexpr curr_expr; /* to protect against an inline being expanded twice
1217: in a simple expression keep track of expressions
1218: being simplified
1219: */
1220: Pstmt stmt::simpl()
1221: /*
1222: return a pointer to the last statement in the list, or 0
1223: */
1224: {
1225: if (this == 0) error('i',"0->S::simpl()");
1226:
1227: Pstmt cstmt = Cstmt;
1228: Cstmt = this;
1229:
1230: curr_expr = e;
1231: //error('d',"stmt::simpl %k s_list %d",base,s_list);
1232:
1233: switch (base) {
1234: default:
1235: error('i',"S::simpl(%k)",base);
1236:
1237: case ASM:
1238: break;
1239:
1240: case BREAK:
1241: if (break_del_list) { // break => { _dtor()s; break; }
1242: Pstmt bs = new stmt(base,where,0);
1243: Pstmt dl = break_del_list->copy();
1244: base = BLOCK;
1245: s = new pair(where,dl,bs);
1246: }
1247: break;
1248:
1249: case CONTINUE:
1250: if (continue_del_list) { // continue => { _dtor()s; continue; }
1251: Pstmt bs = new stmt(base,where,0);
1252: Pstmt dl = continue_del_list->copy();
1253: base = BLOCK;
1254: s = new pair(where,dl,bs);
1255: }
1256: break;
1257:
1258: case DEFAULT:
1259: s->simpl();
1260: break;
1261:
1262: case SM:
1263: if (e) {
1264: if (e->base == DEREF) e = e->e1;
1265: e->simpl();
1266: if (e->base == DEREF) e = e->e1;
1267: }
1268: break;
1269:
1270: case RETURN:
1271: { /* return x;
1272: =>
1273: { dtor()s; return x; }
1274: OR (returning an X where X(X&) is defined) =>
1275: { ctor(_result,x); _dtor()s; return; }
1276: OR (where x needs temporaries)
1277: OR (where x might involve an object to be destroyed) =>
1278: { _result = x; _dtor()s; return _result; }
1279: return; =>
1280: { _dtor()s; return; }
1281: OR (in constructors) =>
1282: { _dtor()s; return _this; }
1283: */
1284: Pstmt sx = this;
1285: Pexpr ex = e;
1286:
1287: no_of_returns++;
1288:
1289: Pstmt dl = (del_list) ? del_list->copy() : 0;
1290: Pfct f = Pfct(curr_fct->tp);
1291:
1292: if (e == 0) e = dummy;
1293: if (e==dummy && curr_fct->n_oper==CTOR) e = f->f_this;
1294:
1295:
1296: // need to generate a temporary for mptr return
1297: Pexpr tt = e;
1298: while ( tt->base == CAST )
1299: tt = tt->e1;
1300: if ( tt->base == ILIST )
1301: e = tt;
1302:
1303: if (e->base == ILIST) {
1304: extern Pbase mptr_type;
1305: extern Ptype Pvptr_type;
1306: Pexpr mptr_assign(Pexpr, Pexpr);
1307: // memptr constant
1308: // return({1,2,f}) ==> memptr t; return((t={1,2,f},&t))
1309:
1310: Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl;
1311: Pname temp = make_tmp('A',mptr_type,ftbl);
1312:
1313: // placed in mptr_assign()
1314: // temp->use(); // necessary for inlines to force declaration
1315:
1316: e = mptr_assign(temp,e);
1317: e = new expr(G_CM,e,temp);
1318: e->tp = mptr_type;
1319: }
1320:
1321: if (f->f_result) { // ctor(_result,x); dtors; return;
1322: if (e->base == G_CM) e = replace_temp(e,f->f_result);
1323: e->simpl();
1324: Pstmt cs = new estmt(SM,where,e,0);
1325: if (dl) cs = new pair(where,cs,dl);
1326: base = PAIR;
1327: s = cs;
1328: s2 = new estmt(RETURN,where,0,0);
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->ret_tp = ret_tp;
1645: base = PAIR;
1646: s = ss;
1647: s2 = rs;
1648: Cstmt = cstmt;
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: Cstmt = cstmt;
1674: return t1 ? t1 : rs;
1675: }
1676: }
1677:
1678: case FOR: // don't know which expression the temp comes from
1679: error('s',&where,"E in %kS needs temporary ofC%nW destructor",base,cln);
1680: break;
1681:
1682: case SM: // place dtors after all "converted" DCLs
1683: if (t1) {
1684: // ccheck(e);
1685: for (Pstmt ttt, tt=this;
1686: (ttt=tt->s_list) && ttt->base==SM;
1687: tt = ttt) ;
1688: t2->s_list = ttt;
1689: tt->s_list = ss;
1690: Cstmt = cstmt;
1691: return t1!=tt ? t1 : t2;
1692: }
1693: default:
1694: def:
1695: // if (e) ccheck(e);
1696: if (t1) { // t1 == tail of statment list
1697: t2->s_list = s_list;
1698: s_list = ss;
1699: Cstmt = cstmt;
1700: return t1;
1701: }
1702: s_list = ss;
1703: Cstmt = cstmt;
1704: return t2;
1705: }
1706: }
1707: Cstmt = cstmt;
1708: return (t1) ? t1 : this;
1709: }
1710:
1711: Cstmt = cstmt;
1712: return (s_list) ? s_list->simpl() : this;
1713: }
1714:
1715: Pstmt stmt::copy()
1716: // now handles dtors in the expression of an IF stmt
1717: // not general!
1718: {
1719: Pstmt ns = new stmt(0,curloc,0);
1720:
1721: *ns = *this;
1722: if (s) ns->s = s->copy();
1723: if (s_list) ns->s_list = s_list->copy();
1724:
1725: switch (base) {
1726: case PAIR:
1727: ns->s2 = s2->copy();
1728: break;
1729: }
1730:
1731: return ns;
1732: }
1733:
1734: void expr::simpl_new()
1735: /*
1736: change NEW or GNEW node to CALL node
1737: */
1738: {
1739: Pname cln;
1740: Pname ctor;
1741: int sz = 1;
1742: // int esz;
1743: Pexpr var_expr = 0;
1744: Pexpr const_expr = 0;
1745: Ptype tt = tp2;
1746: Pexpr arg;
1747: Pexpr szof;
1748: Pname nf;
1749: Pexpr init = e1;
1750:
1751: if (init && init->base) init = 0; // only non-ctor init
1752: //error('d',"use new %d used %d init %d",base,new_used,init);
1753:
1754: if (cln=tt->is_cl_obj()) {
1755: Pclass cl = Pclass(cln->tp);
1756: Pexpr p;
1757: ctor=cl->has_ctor();
1758: //error('d',"cl %t ctor %n",cl, ctor);
1759: if (e2 // placement
1760: || ctor==0 // no constructor
1761: || ctor->n_table!=cl->memtbl // inherited constructor???
1762: ) {
1763: // allocate using operator new(sizeof(cl),args1)
1764: Pexpr ce = new texpr(SIZEOF,tt,0);
1765: (void) tt->tsizeof();
1766: ce->tp = uint_type;
1767: e2 = new expr(ELIST,ce,e2);
1768: char* s = oper_name(NEW);
1769: Pname n = new name(s);
1770: if (base == GNEW) // ::new
1771: p = gtbl->look(s,0);
1772: else
1773: p = find_name(n,cl,scope,CALL,curr_fct);
1774: p = new call(p,e2);
1775: (void) p->call_fct(cl->memtbl);
1776: }
1777: else
1778: p = zero; // 0->ctor(args)
1779:
1780: if (ctor) {
1781: Pexpr c = e1; // ctor call generated in expr::typ
1782: Ptype ttt = tp;
1783: c->e1->e1 = p; // p->ctor
1784: c->simpl();
1785: *this = *c;
1786: tp = ttt;
1787: delete c;
1788: }
1789: else { // (tp)new(args)
1790: base = CAST;
1791: tp2 = tp;
1792: e1 = p;
1793: e2 = 0;
1794: simpl();
1795: }
1796: return;
1797: }
1798:
1799: if (cl_obj_vec) {
1800: Pclass cl = Pclass(cl_obj_vec->tp);
1801: ctor = cl->has_ictor();
1802: if (ctor == 0) {
1803: if (cl->has_ctor()) error("new %s[], no defaultK",cl->string);
1804: cl_obj_vec = 0;
1805: }
1806: }
1807:
1808: xxx:
1809: //error('d',"xxx %t",tt);
1810: switch (tt->base) {
1811: case TYPE:
1812: tt = Pbase(tt)->b_name->tp;
1813: goto xxx;
1814:
1815: default:
1816: (void) tt->tsizeof();
1817: szof = new texpr(SIZEOF,tt,0);
1818: szof->tp = uint_type;
1819: break;
1820:
1821: case VEC:
1822: { Pvec v = Pvec(tt);
1823: //error('d',"v %d %d",v->size,v->dim);
1824: if (v->size)
1825: sz *= v->size;
1826: else if (v->dim)
1827: var_expr = v->dim;
1828: else
1829: sz = 0;
1830: tt = v->typ;
1831: goto xxx;
1832: }
1833: }
1834:
1835: if (cl_obj_vec) { // _vec_new(0,no_of_elements,element_size,ctor)
1836: const_expr = new ival(sz);
1837: Pexpr noe = (var_expr) ? (sz!=1) ? new expr(MUL,const_expr,var_expr) : var_expr : const_expr;
1838: const_expr = szof;
1839: const_expr->tp = uint_type;
1840: base = CALL;
1841: arg = new expr(ELIST,ctor,0);
1842: /*ctor->take_addr();*/
1843: ctor->lval(ADDROF);
1844: arg = new expr(ELIST,const_expr,arg);
1845: arg = new expr(ELIST,noe,arg);
1846: arg = new expr(ELIST,e2?e2:zero,arg); // may be preallocated
1847: base = CAST;
1848: tp2 = tp;
1849: e1 = new expr(G_CALL,vec_new_fct,arg);
1850: e1->fct_name = vec_new_fct;
1851: e1->tp = Pfct(vec_new_fct->tp)->returns;
1852: simpl();
1853: return;
1854: }
1855:
1856: /* call _new(element_size*no_of_elements) */
1857: //error('d',"sz %d var %d",sz,var_expr);
1858: if (sz == 1)
1859: arg = (var_expr) ? new expr(MUL,szof,var_expr) : szof;
1860: else {
1861: const_expr = new ival(sz);
1862: const_expr->tp = uint_type;
1863: const_expr = new expr(MUL,const_expr,szof);
1864: const_expr->tp = uint_type;
1865: arg = (var_expr) ? new expr(MUL,const_expr,var_expr) : const_expr;
1866: }
1867:
1868: arg->tp = uint_type;
1869: base = CAST;
1870: tp2 = tp;
1871: arg = new expr(ELIST,arg,e2);
1872: nf = gtbl->look(oper_name(NEW),0); // always global,
1873: // all class object handled above
1874: e1 = new expr(G_CALL,nf,arg);
1875: (void) e1->call_fct(gtbl);
1876: simpl();
1877:
1878: if (init) { // alloc(sz) => (p=alloc(sz),*p=init,p);
1879: Pexpr p = init->e1;
1880: Pexpr ee = new expr(0,0,0);
1881: *ee = *this;
1882: ee = new expr(ASSIGN,p,ee); // ee: p = alloc(sz);
1883: init->base = ASSIGN;
1884: init->e1 = p->contents(); // init: *p = init_val
1885: ee = new expr(CM,ee,init);
1886: base = CM;
1887: e1 = ee;
1888: e2 = p;
1889: }
1890: }
1891:
1892: void expr::simpl_delete()
1893: /*
1894: delete p => _delete(p);
1895: or cl::~cl(p,1);
1896: delete[s]p => _delete(p);
1897: or vec_del_fct(p,vec_sz,elem_sz,~cl,1);
1898: */
1899: {
1900: for (Ptype tt = e1->tp; tt->base==TYPE; tt=Pbase(tt)->b_name->tp);
1901: tt = Pptr(tt)->typ;
1902: //error('d',"simpl_delete() %t",e1->tp);
1903: Pname cln = tt->is_cl_obj();
1904: Pname n;
1905: Pclass cl;
1906:
1907: if (cln) {
1908: cl = Pclass(cln->tp);
1909: if ((cl->defined&DEFINED) == 0) error('w',"delete%t (%t not defined)",cl,cl);
1910: }
1911: else
1912: cl = 0;
1913:
1914: if (cl && (n=cl->has_dtor())) { // ~cl() might be virtual
1915: Pexpr r = e1;
1916:
1917: // handle delete p, where p has a private destructor
1918: if (n->n_scope != PUBLIC) check_visibility(n,0,cl,cc->ftbl,cc->nof);
1919: //error('d',"e2 %d %k",e2,base);
1920: if (e2 == 0) { // e1->cl::~cl(1)
1921: Pexpr ee = call_dtor(r,n,base==GDELETE?0:one,REF,one);
1922: if (Pfct(n->tp)->f_virtual) {
1923: extern nin;
1924: nin = 1;
1925: if (r->not_simple()) error('s',"PE too complicated for delete");
1926: nin = 0;
1927: #ifndef sun
1928: if (ansi_opt) { // q?void:int would be an error
1929: #endif
1930: ee = new expr(G_CM,ee,zero);
1931: ee->tp = zero_type;
1932: #ifndef sun
1933: }
1934: #endif
1935: ee = new expr(QUEST,ee,zero);
1936: ee->tp = ee->e1->tp;
1937: ee->cond = r;
1938: }
1939: if (base == GDELETE) {
1940: char* s = oper_name(DELETE);
1941: Pexpr p = gtbl->look(s,0);
1942: e2 = new call(p,e1);
1943: base = CM;
1944: e1 = ee;
1945: }
1946: else {
1947: *this = *ee;
1948: delete ee;
1949: }
1950: simpl();
1951: return;
1952: }
1953: else { // del_cl_vec(e1,e2,elem_size,~cl,1);
1954: Pexpr sz = new texpr(SIZEOF,tt,0);
1955: (void)tt->tsizeof();
1956: Pfct f = Pfct(n->tp);
1957: int i = 0;
1958: for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) i++;
1959: //error('d',"n %n i %d",n,i);
1960: Pexpr arg = new ival(i);
1961: sz->tp = uint_type;
1962: // Pexpr arg = one;
1963: arg = new expr(ELIST,one,arg);
1964: if (Pfct(n->tp)->f_virtual) {
1965: // beware of sideeffects in expression e1
1966:
1967: extern nin;
1968: nin = 1;
1969: if (r->not_simple()) error('s',"PE too complicated for delete[]");
1970: nin = 0;
1971: Pexpr a = new ref(REF,e1,n);
1972: a = a->address();
1973: a = new mdot( "f", a );
1974: a->i1 = 9;
1975: arg = new expr(ELIST,a,arg);
1976: }
1977: else {
1978: arg = new expr(ELIST,n,arg);
1979: n->lval(ADDROF); // n->take_addr();
1980: }
1981: arg = new expr(ELIST,sz,arg);
1982: arg = new expr(ELIST,e2,arg);
1983: arg = new expr(ELIST,e1,arg);
1984: Pexpr ee = new expr(G_CALL,vec_del_fct,arg);
1985: ee->fct_name = vec_del_fct;
1986: ee->tp = tp;
1987: // if (ansi_opt) { // q?void:int would be an error
1988: // ee = new expr(G_CM,ee,zero);
1989: // ee->tp = zero_type;
1990: // }
1991: // ee = new expr(QUEST,ee,zero);
1992: // ee->tp = tp;
1993: // ee->cond = r;
1994: *this = *ee;
1995: simpl();
1996: return;
1997: }
1998: }
1999: else if (cl_obj_vec) {
2000: error("delete array of arrays");
2001: }
2002: else { // _delete(e1)
2003: Pexpr ee = new expr(ELIST,e1,0);
2004: char* s = oper_name(DELETE);
2005: if (cl && base!=GDELETE) {
2006: Pname n = new name(s);
2007: e1 = find_name(n,cl,scope,CALL,curr_fct);
2008: if (e1->tp->base==OVERLOAD || Pfct(e1->tp)->nargs==2) {
2009: Pexpr ss = new texpr(SIZEOF,cl,0);
2010: ss->tp = uint_type;
2011: ee->e2 = new expr(ELIST,ss,0);
2012: }
2013: }
2014: else
2015: e1 = gtbl->look(s,0);
2016: base = G_CALL;
2017: e2 = ee;
2018: (void) call_fct(scope);
2019: }
2020:
2021: Pcall(this)->simpl();
2022: }
2023: /* ODI notes
2024:
2025: set Cstmt to get better error messages
2026:
2027: on sun, don't convert void to char *
2028:
2029: ditch support for RETBUG, it made a union hard to walk in the tree.
2030: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.