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

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

unix.superglobalmegacorp.com

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