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

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

unix.superglobalmegacorp.com

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