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

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

unix.superglobalmegacorp.com

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