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