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