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

unix.superglobalmegacorp.com

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