Annotation of researchv10no/cmd/cfront/cfront2.00/simpl2.c, revision 1.1

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

unix.superglobalmegacorp.com

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