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

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

unix.superglobalmegacorp.com

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