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

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

unix.superglobalmegacorp.com

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