Annotation of researchv10no/cmd/cfront/ptcfront/simpl2.c, revision 1.1.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.