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