|
|
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.