Annotation of researchv10no/cmd/cfront/ooptcfront/simpl2.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.