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