Annotation of researchv10no/cmd/cfront/ooptcfront/simpl.c, revision 1.1

1.1     ! root        1: /*ident        "@(#)ctrans:src/simpl.c 1.5.4.25" */
        !             2: /******************************************************************
        !             3: 
        !             4:        C++ source for cfront, the C++ compiler front-end
        !             5:        written in the computer science research center of Bell Labs
        !             6: 
        !             7:        Copyright (c) 1984 AT&T, Inc. All rigths Reserved
        !             8:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
        !             9: 
        !            10: simpl.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: 
        !            31: Pname new_fct;
        !            32: Pname del_fct;
        !            33: Pname vec_new_fct;
        !            34: Pname vec_del_fct;
        !            35: 
        !            36: Pstmt del_list;
        !            37: Pstmt break_del_list;
        !            38: Pstmt continue_del_list;
        !            39: 
        !            40: //bit not_inl; // is the current function an inline?
        !            41: Pname curr_fct;        // current function
        !            42: Pexpr init_list;
        !            43: Pexpr one;
        !            44: 
        !            45: Ptype Pfct_type;
        !            46: Ptype Pvptr_type;
        !            47: Pbase mptr_type;
        !            48: Ptype size_t_type;
        !            49: 
        !            50: Pexpr cdvec(Pname f, Pexpr vec, Pclass cl, Pname cd, int,Pexpr);
        !            51: Pstmt trim_tail(Pstmt tt);
        !            52: Pname find_vptr(Pclass);
        !            53: char *get_classname(char*);
        !            54: char *drop_classname(char*);
        !            55: loc no_where;  // 0,0
        !            56: 
        !            57: int imeasure;  // a counter trying to measure the complexity of a function
        !            58:                // body to try to avoid expanding ``monster'' inlines.
        !            59: 
        !            60: extern Pexpr initialize_vptrs (Pclass cl, Pexpr this_expr);
        !            61: 
        !            62:     /* Constructs an expression which initializes the given class's vptrs.
        !            63:        The this_expr forms the first part of the path expression for each
        !            64:        vptr assignment. The vptr assignments are combined into a comma
        !            65:        expression. */
        !            66:        
        !            67: 
        !            68: static Pclass topclass;
        !            69: 
        !            70: void simpl_init()
        !            71: {
        !            72:        char* ns = oper_name(NEW);
        !            73:        char* ds = oper_name(DELETE);
        !            74: 
        !            75:        size_t_type = Pvoid_type->tsizeof()>uint_type->tsizeof()?ulong_type:uint_type;
        !            76: 
        !            77:        Pname nw = new name(ns);
        !            78:        nw->n_oper = NEW;
        !            79:        Pname a = new name;
        !            80:        a->tp = size_t_type;
        !            81:        nw->tp = new fct(Pvoid_type,a,1);
        !            82:        new_fct = nw->dcl(gtbl,EXTERN); // void* operator new(long);
        !            83:        delete nw;
        !            84:  //    new_fct->use();
        !            85: 
        !            86:        Pname dl = new name(ds);
        !            87:        dl->n_oper = DELETE;
        !            88:        a = new name;
        !            89:        a->tp = Pvoid_type;
        !            90:        dl->tp = new fct(void_type,a,1);
        !            91:        del_fct = dl->dcl(gtbl,EXTERN);
        !            92:        delete dl;
        !            93:  //    del_fct->use();
        !            94: 
        !            95: 
        !            96:        Pname vn = new name("__vec_new");
        !            97:        Pname vd = new name("__vec_delete");
        !            98: 
        !            99:        a = new name;
        !           100:        a->tp = Pvoid_type;
        !           101:        Pname al = a;
        !           102:        a = new name;
        !           103:        a->tp = int_type;
        !           104:        a->n_list = al;
        !           105:        al = a;
        !           106:        a = new name;
        !           107:        a->tp = int_type;
        !           108:        a->n_list = al;
        !           109:        al = a;
        !           110:        a = new name;   
        !           111:        a->tp = Pvoid_type;
        !           112:        a->n_list = al;
        !           113:        al = a;                         /* (Pvoid, int, int, Pvoid) */
        !           114: 
        !           115:        vec_new_fct = gtbl->insert(vn,0);
        !           116:        delete vn;
        !           117:        vec_new_fct->tp = new fct(Pvoid_type,al,1);
        !           118:        vec_new_fct->n_scope = EXTERN;
        !           119:        PERM(vec_new_fct);
        !           120:        PERM(vec_new_fct->tp);
        !           121:        vec_new_fct->use();
        !           122: 
        !           123:         vec_new_fct->dcl_print(0);
        !           124: 
        !           125:        a = new name;
        !           126:        a->tp = int_type;
        !           127:        al = a;
        !           128:        a = new name;
        !           129:        a->tp = int_type;
        !           130:        a->n_list = al;
        !           131:        al = a;
        !           132:        a = new name;
        !           133:        a->tp = Pvoid_type;
        !           134:        a->n_list = al;
        !           135:        al = a;
        !           136:        a = new name;
        !           137:        a->tp = int_type;
        !           138:        a->n_list = al;
        !           139:        al = a;
        !           140:        a = new name;
        !           141:        a->tp = int_type;
        !           142:        a->n_list = al;
        !           143:        al = a;
        !           144:        a = new name;   
        !           145:        a->tp = Pvoid_type;
        !           146:        a->n_list = al;
        !           147:        al = a;                         /* (Pvoid, int, int, Pvoid, int, int) */
        !           148: 
        !           149:        vec_del_fct = gtbl->insert(vd,0);
        !           150:        delete vd;
        !           151:        vec_del_fct->tp = new fct(void_type,al,1);
        !           152:        vec_del_fct->n_scope = EXTERN;
        !           153:        PERM(vec_del_fct);
        !           154:        PERM(vec_del_fct->tp);
        !           155:        vec_del_fct->use();
        !           156: 
        !           157:         vec_del_fct->dcl_print(0);
        !           158: 
        !           159:        one = new ival(1);
        !           160:        one->tp = int_type;
        !           161:        PERM(one);
        !           162:        
        !           163:        Pfct_type = new fct(int_type,0,1);      // int (*)()
        !           164:        Pfct_type = Pfct_type->addrof();
        !           165:        PERM(Pfct_type);
        !           166: 
        !           167:         putstring("typedef int (*__vptp)();\n");
        !           168:         putstring("struct __mptr {short d; short i; __vptp f; };\n");
        !           169: 
        !           170:        Pname b = new name("__mptr");
        !           171:         b->tp = new classdef(STRUCT);
        !           172:         b->tp->defined = 1;
        !           173:         Pclass(b->tp)->obj_size = 8;
        !           174:        mptr_type = new basetype(COBJ,b);
        !           175:        PERM(mptr_type);
        !           176: 
        !           177:        Pvptr_type = mptr_type->addrof();
        !           178:        PERM(Pvptr_type);
        !           179: }
        !           180: 
        !           181: Ptable scope;          /* current scope for simpl() */
        !           182: Pname expand_fn;       /* name of function being expanded or 0 */
        !           183: Ptable expand_tbl;     /* scope for inline function variables */
        !           184: 
        !           185: Pname classdef::has_oper(TOK op)
        !           186: {
        !           187:        Pexpr n = find_name(oper_name(op),0);
        !           188:        if (n == 0) return 0;
        !           189: 
        !           190:        while (n->base==REF || n->base==MDOT) {
        !           191:                Pexpr e = Pexpr(n);
        !           192:                n = Pname(n->mem);
        !           193:                delete e;
        !           194:        }
        !           195:        if (n->tp->base==FCT && Pname(n)->n_dcl_printed==0) Pname(n)->dcl_print(0);
        !           196:        return Pname(n);
        !           197: }
        !           198: 
        !           199: int is_expr(Pstmt s)
        !           200: /*
        !           201:        is this statement simple enough to be converted into an expression for
        !           202:        inline expansion?
        !           203: */
        !           204: {
        !           205:        int i = 0;
        !           206:        if (s->base == BLOCK) {
        !           207:                if (s->s == 0) return 1;
        !           208:                s = s->s;
        !           209:        }
        !           210:        for (Pstmt ss = s; ss; ss = ss->s_list) {
        !           211: //error('d',"ss %k",ss->base);
        !           212:                switch (ss->base) {
        !           213:                case BLOCK:
        !           214:                        if (Pblock(ss)->memtbl || is_expr(ss->s)==0) return 0;
        !           215:                case SM:
        !           216:                        if (ss->e && ss->e->base==ICALL) {
        !           217:                                Pname fn = ss->e->il->fct_name;
        !           218:                                Pfct f = Pfct(fn->tp);
        !           219:                                if (f->f_expr == 0) return 0;
        !           220:                        }
        !           221:                        break;
        !           222:                case IF:
        !           223:                        if (is_expr(ss->s)==0) return 0;
        !           224:                        if (ss->else_stmt && is_expr(ss->else_stmt)==0) return 0;
        !           225:                        break;
        !           226:                default:
        !           227:                        return 0;
        !           228:                }
        !           229:                i++;
        !           230:        }
        !           231:        return i;
        !           232: }
        !           233: 
        !           234: int no_of_returns;
        !           235: 
        !           236: void name::simpl()
        !           237: {
        !           238: //error('d',"name::simpl%n %d %k",this,tp->base,tp->base);
        !           239:        if (base == PUBLIC) return;
        !           240: 
        !           241:        if (tp == 0) error('i',"%n->N::simple(tp==0)",this);
        !           242: 
        !           243:        switch (tp->base) {
        !           244:        case 0:
        !           245:                error('i',"%n->N::simpl(tp->B==0)",this);
        !           246: 
        !           247:        case OVERLOAD:
        !           248:        {       for (Plist gl = Pgen(tp)->fct_list; gl; gl=gl->l) gl->f->simpl();
        !           249:                break;
        !           250:        }
        !           251: 
        !           252:        case FCT:
        !           253:        {       Pfct f = Pfct(tp);
        !           254:                Pname n;
        !           255:                Pname th = f->f_this;
        !           256: 
        !           257:                if (th) {
        !           258:                        // Make "this" a register if it is used more than twice:
        !           259:                        if (th->n_addr_taken) error("&this");
        !           260:                        th->n_stclass = (2 < th->n_used) ? REGISTER : AUTO;
        !           261:                        if (warning_opt
        !           262:                        && th->n_assigned_to
        !           263:                        && th->n_assigned_to!=FUDGE111)
        !           264:                                error('w',&where,"assignment to this");
        !           265:                }
        !           266: 
        !           267: 
        !           268:                if (ansi_opt && f->body==0) {
        !           269:                // make sure arguments can be printed for decls
        !           270:                        
        !           271:                        for (Pname n = f->f_args; n; n = n->n_list) {
        !           272:                                n->n_scope = ARG;
        !           273:                                if (n->string) {
        !           274:                                        char* ps = new char[strlen(n->string)+1];
        !           275:                                        strcpy(ps,n->string);
        !           276:                                        n->string = ps;
        !           277:                                }
        !           278: /*
        !           279:                                if (n_oper==DTOR && n->n_list==0) {
        !           280:                                        // add __free argument
        !           281:                                        Pname fa=new name;
        !           282:                                        fa->tp = int_type;
        !           283:                                        n->n_scope = ARG;
        !           284:                                //      ps = new char[6];
        !           285:                                //      strcpy(ps, "__free");
        !           286:                                //      fa->string = ps;
        !           287:                                        n->n_list = fa;
        !           288:                                        break;
        !           289:                                }
        !           290: */
        !           291:                        }
        !           292:                }
        !           293: 
        !           294:                if (tp->defined & (SIMPLIFIED | ~DEFINED) ) return;
        !           295: 
        !           296:                for (n=f->f_args; n; n=n->n_list) n->simpl();
        !           297: 
        !           298:                if (f->body) {
        !           299:                        Ptable oscope = scope;
        !           300:                        Pname ocurr = curr_fct;
        !           301:                        int oim = imeasure;
        !           302:                        scope = f->body->memtbl;
        !           303: //error('d',"body");
        !           304:                        if (scope == 0) error('i',"%n memtbl missing",this);
        !           305:                        curr_fct = this;
        !           306:                        f->simpl();
        !           307:                        if (f->f_inline==0 || debug_opt)
        !           308:                                f->f_imeasure = 0;      // not a converted inline
        !           309:                        else {
        !           310:                                // first check if the function is too large to
        !           311:                                // be worth inlining
        !           312:                                if (12<f->f_imeasure) { // cut-over point:
        !           313:                                                        // about 12 assignments
        !           314:                                                        // f->f_imeasure indicates
        !           315:                                        f->f_inline = 0;// a converted inline
        !           316: //error('d',"don't inline%n %d %d %d",this,this,f,f->f_imeasure);
        !           317:                                        tp->defined |= SIMPLIFIED;
        !           318:                                        return;
        !           319:                                }
        !           320:                                int i = 0;
        !           321:                                for (n=f->f_args; n; n=n->n_list) {
        !           322:                                        n->base = ANAME;
        !           323:                                        n->n_val = i++;
        !           324:        // ??                           if (n->n_table != scope) error('i',"aname scope: %d %n %d %d\n",n,n,n->n_table,scope);
        !           325:                                }
        !           326:                                expand_tbl = (f->returns->base!=VOID || n_oper==CTOR) ? scope : 0;
        !           327:                                expand_fn = this;
        !           328: 
        !           329:                                if (expand_tbl) {
        !           330:                                genlab:
        !           331:                                                // value returning: generate expr
        !           332:                                                // the body still holds the memtbl
        !           333:                                        Pexpr ee = Pexpr(f->body->expand());
        !           334:                                        Ptype t = 0;
        !           335:                                        if (f->s_returns) {
        !           336:                                                if (ee->tp!=f->s_returns) t = f->s_returns;
        !           337:                                        }
        !           338:                                        else if (ee->tp!=f->returns)
        !           339:                                                t = f->returns;
        !           340:                                        // VCVC assumes VOID is output as CHAR:
        !           341: /* But this is not needed on a sun, and just makes the debugger print trash */
        !           342: #ifndef sun
        !           343:                                        if (t && t==void_type && ansi_opt == 0)
        !           344:                                                ee = new expr(CM,ee,new cast(char_type,zero));
        !           345: #endif
        !           346:                                        f->f_expr = (ee->base==CM) ? ee : new expr(CM,zero,ee);
        !           347:                                        // print.c assumes expansion into comma expression
        !           348:                                }
        !           349:                                else {
        !           350:                                        if (is_expr(f->body)) {
        !           351:                                                // can generate expr: do
        !           352:                                                expand_tbl = scope;
        !           353:                                                goto genlab;
        !           354:                                        }
        !           355:                                        // not value return: can generate block
        !           356:                                        f->f_expr = 0;
        !           357:                                        f->body = Pblock(f->body->expand());
        !           358:                                }
        !           359:                                expand_fn = 0;
        !           360:                                expand_tbl = 0;
        !           361:                        }
        !           362:                        scope = oscope;
        !           363:                        curr_fct = ocurr;
        !           364:                        imeasure = oim;
        !           365:                }
        !           366:                break;
        !           367:        }
        !           368: 
        !           369:        case CLASS:
        !           370:                Pclass(tp)->simpl();
        !           371:        }
        !           372: 
        !           373:        if (n_initializer) n_initializer->simpl();
        !           374:        tp->defined |= SIMPLIFIED;
        !           375: }
        !           376: 
        !           377: Pexpr call_ctor(Ptable tbl, Pexpr p, Pexpr ctor, Pexpr args, int d, Pexpr vb_args)
        !           378: {
        !           379:        Pexpr ee = new ref(d,p,ctor);
        !           380:        if (p==0 || tbl==0) ee->tp = ctor->tp;
        !           381: //error('d',"call_ctor(tbl %d, p %d, %n, args %d)",tbl,p,ctor,args);
        !           382:        if (args && args->base!=ELIST) args = new expr(ELIST,args,0);
        !           383:        ee = new expr(G_CALL,ee,args);
        !           384:        Pname n = Pname(ctor);
        !           385:        while (n->base == MDOT) n = Pname(n->mem);
        !           386:        if (n->tp->base == FCT) ee->fct_name = n;
        !           387:        if (tbl)
        !           388:                ee = ee->typ(tbl);
        !           389:        else if (n->tp->base == FCT)
        !           390:                ee->tp = Pfct(n->tp)->s_returns;
        !           391:        if (ee->tp == any_type) return ee;
        !           392:        args = ee->e2;
        !           393: 
        !           394:        if (vb_args == 0) {             // attach zero vbase arguments
        !           395:                Pfct f = Pfct(ee->fct_name->tp);        // not n->fct_name
        !           396:                for (Pname nn = f->f_args->n_list; nn && nn!=f->argtype; nn=nn->n_list)
        !           397:                        args = new expr(ELIST,zero,args);
        !           398:        }
        !           399:        else {                          // attach vbase arguments
        !           400:                if (args) {
        !           401:                        for (Pexpr d = vb_args; d->e2; d=d->e2);
        !           402:                        d->e2 = args;
        !           403:                }
        !           404:                args = vb_args;
        !           405:        }
        !           406: 
        !           407:        ee->e2 = args;
        !           408:        return ee;
        !           409: }
        !           410: 
        !           411: Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg, int d, Pexpr vb_args)
        !           412: {
        !           413: // error('d',"call dtor %k %n %t vb_args %d",d,dtor,dtor->tp,vb_args);
        !           414:        Pexpr r = new ref(d,p,dtor);
        !           415: 
        !           416:        if (arg && vb_args) {
        !           417:                arg = new ival(3);
        !           418:                arg->tp = int_type;
        !           419:        }
        !           420:        else if (vb_args) {
        !           421:                arg = new ival(2);
        !           422:                arg->tp = int_type;
        !           423:        }
        !           424:        else if (arg==0)
        !           425:                arg = zero;
        !           426: 
        !           427:        Pexpr aa = new expr(ELIST,arg,0); // argument controlling deallocation
        !           428:                                          // 2: destroy vbases
        !           429:                                          // 1: dealllocate, 0: don't
        !           430: 
        !           431:        Pfct f = Pfct(dtor->tp);                // attach virtual base arguments
        !           432: //     for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) {
        !           433: //             Pexpr xx = vb_args ? new cast(nn->tp,one) : zero;
        !           434: //             aa = new expr(ELIST,xx,aa);
        !           435: //     }
        !           436: 
        !           437: 
        !           438:        Pexpr ee = new call(r,aa);
        !           439:        while (dtor->base == MDOT) dtor = dtor->mem;
        !           440:        if (d == REF)   // could be virtual
        !           441:                ee->fct_name = Pname(dtor);
        !           442:        else {  // virtual suppressed, store fct name 
        !           443:                r->n_initializer = dtor;
        !           444:                ee->fct_name = 0;
        !           445:        }
        !           446:        ee->base = G_CALL;
        !           447:        ee->tp = void_type;
        !           448: 
        !           449:         if (f->memof->c_body == 1) f->memof->dcl_print(0);
        !           450:        if (Pname(dtor)->n_dcl_printed==0) Pname(dtor)->dcl_print(0);
        !           451: 
        !           452:        return ee;
        !           453: }
        !           454: 
        !           455: //extern int new_used; // pre-define new and delete only if the user didn't
        !           456: 
        !           457: Pstmt fct::dtor_simpl(Pclass cl, Pexpr th)
        !           458: {
        !           459:        Pstmt dtail = 0;
        !           460: //error('d',"simpl_dtor(%t) a %d",cl,f_args);
        !           461: //     if (new_used == 0) new_init();
        !           462: 
        !           463:        Pname fa = new name("__free");  // fake argument for dtor
        !           464:        fa->tp = int_type;
        !           465:        Pname free_arg = fa->dcl(body->memtbl,ARG);
        !           466:        free_arg->where = no_where;
        !           467:        delete fa;
        !           468:        Pname a = f_args;
        !           469:        if (a==0 || a->n_list==0) error('i',"__freeA missing in destructor for %t",cl);
        !           470:        Pname p = 0;
        !           471:        for(;;p=a,a=a->n_list) {        // replace nameless fake argument
        !           472: //error('d',"a %d %t",a,a->tp);
        !           473:                if (a->n_list == 0) {
        !           474:                //      a->n_list = free_arg;
        !           475:                        DEL(p->n_list);
        !           476:                        p->n_list = free_arg;
        !           477:                        break;
        !           478:                }
        !           479:        } 
        !           480: 
        !           481:        // generate calls to destructors for all members of class cl:
        !           482:        Ptable tbl = cl->memtbl;
        !           483:        int i = 1;
        !           484:        for (Pname m=tbl->get_mem(i); m; m=tbl->get_mem(++i) ) {
        !           485: 
        !           486:                if (m->n_stclass == STATIC) continue;
        !           487: 
        !           488:                Ptype t = m->tp;
        !           489:                Pexpr ee = 0;
        !           490:                Pname cn;
        !           491:                Pname dtor;
        !           492: 
        !           493:                if (cn = t->is_cl_obj()) {
        !           494:                        Pclass cl = (Pclass)cn->tp;
        !           495:                        if (dtor = cl->has_dtor()) {    // dtor(this,0,ones);
        !           496:                                ee = new ref(REF,th,m);
        !           497:                                ee->tp = m->tp;
        !           498:                                ee = call_dtor(ee,dtor,0,DOT,one);
        !           499:                                check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct);
        !           500:                        }
        !           501:                }
        !           502:                else if (cl_obj_vec) {
        !           503:                        Pclass cl = Pclass(cl_obj_vec->tp);
        !           504:                        if (dtor = cl->has_dtor()) {
        !           505:        Pfct f = Pfct(dtor->tp);
        !           506:        int i = 0;
        !           507:        for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) i++;
        !           508: //error('d',"dtor %n i %d",dtor,i);
        !           509:                                ee = new ref(REF,th,m);
        !           510:                                ee->tp = m->tp;
        !           511:                                ee = cdvec(vec_del_fct,ee,cl,dtor,0,new ival(i));
        !           512:                                check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct);
        !           513:                        }
        !           514:                }
        !           515: 
        !           516:                if (ee) {
        !           517:                        Pstmt es = new estmt(SM,curloc,ee,0);
        !           518:                        // reverse order of destructors for members
        !           519:                        es->s_list = del_list;
        !           520:                        del_list = es;
        !           521:                        if (dtail == 0) dtail = es;
        !           522:                }
        !           523:        }
        !           524: 
        !           525: 
        !           526:        Pexpr ee = 0;
        !           527:        // look for bases with destructors:
        !           528:        // generate: dtor(base,0);
        !           529: 
        !           530:        Pbcl b = 0;     // get dtors in order with virtual bases last
        !           531:        Pbcl t = 0;
        !           532:        for (Pbcl l = cl->baselist; l; l=l->next) {
        !           533:                if (l->base != VIRTUAL) {
        !           534:                        Pbcl x = new basecl(l->bclass,0);
        !           535:                        if (t == 0)
        !           536:                                b  = x;
        !           537:                        else
        !           538:                                t->next = x;
        !           539:                        t = x;
        !           540:                        x->base = l->base;
        !           541:                        x->obj_offset = l->obj_offset;
        !           542:                }
        !           543:        }
        !           544:        for (l = cl->baselist; l; l=l->next) {
        !           545:                if (l->base == VIRTUAL) {
        !           546:                        b = new basecl(l->bclass,b);
        !           547:                        b->base = l->base;
        !           548:                        b->obj_offset = l->obj_offset;
        !           549:                }
        !           550:        }
        !           551:        Pexpr ve = 0;
        !           552: 
        !           553:        for (; b; b=l) {
        !           554:                Pclass bcl = b->bclass;
        !           555:                l = b->next;
        !           556:                Pname dtor = bcl->has_dtor();
        !           557: 
        !           558:                if (dtor) {
        !           559:                        Pexpr val = rptr(bcl->this_type,th,b->obj_offset);
        !           560:                        val = val->contents();
        !           561:                        Pexpr e = call_dtor(val,dtor);
        !           562:                        if (b->base == VIRTUAL) {
        !           563:                                // if (x) this->x.dtor(); where x is a vbase
        !           564:                                for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list) 
        !           565:                                if (strcmp(dd->string,bcl->string)==0) break;
        !           566: 
        !           567: #ifndef sun
        !           568:                                if (ansi_opt) { // q?void:int would be an error
        !           569: #endif
        !           570:                                        e = new expr(G_CM,e,zero);
        !           571:                                        e->tp = zero_type;
        !           572: #ifndef sun
        !           573:                                }
        !           574: #endif
        !           575:                                e = new expr(QUEST,e,zero);
        !           576:                                Pexpr two = new ival(2);
        !           577:                                two->tp = int_type;
        !           578:                                e->cond = new expr (AND,free_arg,two);//dd;
        !           579:                        }
        !           580:                        ee = ee ? new expr(CM,e,ee) : e;
        !           581:                }
        !           582:                delete b;
        !           583:        }
        !           584: 
        !           585:        Pstmt es = ee ? new estmt(SM,curloc,ee,0) : 0;
        !           586: 
        !           587:        ee = new expr(ELIST,th,0);      // free storage
        !           588:        Pname n = new name(oper_name(DELETE));
        !           589:        Pexpr del = find_name(n,cl,scope,CALL,curr_fct);
        !           590:        if (del->tp->base==OVERLOAD || Pfct(del->tp)->nargs==2) {
        !           591:                Pexpr ss = new texpr(SIZEOF,cl,0);
        !           592:                ss->tp = uint_type;
        !           593:                ee->e2 = new expr(ELIST,ss,0);
        !           594:        }
        !           595:        ee = new call(del,ee);
        !           596:        ee->tp = ee->call_fct(scope);
        !           597: 
        !           598:        Pstmt ess = new estmt(SM,curloc,ee,0);
        !           599:        ess = new ifstmt(curloc,new expr(AND,free_arg,one),ess,0);
        !           600:        if (es)
        !           601:                es->s_list = ess;
        !           602:        else
        !           603:                es = ess;
        !           604: 
        !           605:        free_arg->use();
        !           606:        Pname(th)->use();
        !           607: 
        !           608:        if (dtail)
        !           609:                dtail->s_list = es;
        !           610:        else
        !           611:                del_list = es;
        !           612: 
        !           613:        del_list = new ifstmt(curloc,th,del_list,0);
        !           614:        if (del_list) del_list->simpl();
        !           615:        return dtail;
        !           616: }
        !           617: 
        !           618: 
        !           619: Pclass find_vbase_ptr(Pclass cl, Pclass vbase)
        !           620: {
        !           621:        for (Pbcl bb = cl->baselist; bb; bb = bb->next) {
        !           622:                if (bb->bclass==vbase && bb->ptr_offset) return cl;
        !           623:                Pclass f = find_vbase_ptr(bb->bclass,vbase);
        !           624:                if (f) return f;
        !           625:        }
        !           626:        return 0;
        !           627: }
        !           628: 
        !           629: Pclass second_base(Pclass cl, Pclass base)
        !           630: {
        !           631: //error('d',"second_base(%t,%t)",cl,base);
        !           632:        for (Pbcl b = cl->baselist; b && b->base==NAME; b = b->next) {
        !           633:                if (b->bclass==base) {
        !           634:                        if (b==cl->baselist) return 0;
        !           635:                        return base;
        !           636:                }
        !           637:                Pclass bb = second_base(b->bclass,base);
        !           638:                if (bb == Pclass(-1)) continue; // not found
        !           639:                if (bb) {
        !           640:                        if (b!=cl->baselist) error('s',"C hierarchy too complicated");
        !           641:                        return bb;      // second base of b->bclass
        !           642:                }
        !           643:                if (b==cl->baselist) return 0;
        !           644:                return b->bclass;       // b->bclass is second base
        !           645:        }
        !           646:        return Pclass(-1);
        !           647: }
        !           648: 
        !           649: //Pclass topclass;
        !           650: 
        !           651: Pexpr classdef::get_vptr_exp(char *s)
        !           652: {
        !           653: //error('d',"%t::get_vptr_exp(%s)",this,s?s:"0");
        !           654:        if (c_body == 1) dcl_print(0);
        !           655:        if (c_body == 3) print_all_vtbls(this);
        !           656:        if (s == 0) return find_vptr(this);
        !           657:        Pbcl b = get_base(get_classname(s));
        !           658:        Pexpr vp = b->bclass->get_vptr_exp(drop_classname(s));
        !           659:        if (b==baselist && b->base!=VIRTUAL) return vp;
        !           660:        vp = new mdot(b->bclass->string,vp);
        !           661:        if (c_body == 1) b->bclass->dcl_print(0);
        !           662:        if (c_body == 3) b->bclass->print_all_vtbls(b->bclass);
        !           663:        if (b->base == VIRTUAL) {
        !           664:                vp->i1 = 1;
        !           665:                if (b->ptr_offset == 0) { // pointer to base in intermediate base
        !           666:                        Pclass bb = find_vbase_ptr(this,b->bclass);
        !           667:                        Pclass sb = second_base(topclass,bb);
        !           668: //error('d',"mdot %t %t : %d %t ",topclass,bb,sb,sb==Pclass(-1)?0:sb);
        !           669:                        if (sb && sb!=Pclass(-1)) vp = new mdot(sb->string,vp);
        !           670:                }
        !           671:        }
        !           672:        return vp;
        !           673: }
        !           674: 
        !           675: int fct::ctor_simpl(Pclass cl, Pexpr th)
        !           676: {
        !           677:        Ptable tbl = cl->memtbl;
        !           678: 
        !           679:        int ass_count = 0;
        !           680:        init_list = 0;
        !           681: //error('d',"ctor_simpl %t: %t",cl,this);
        !           682:        /*
        !           683:                initialization order:
        !           684:                (1)     virtual base pointers and virtual bases
        !           685:                                (they may be used in non-virtual bases)
        !           686:                (2)     non-virtual bases
        !           687:                (3)     virtual function pointers
        !           688:                (4)     members
        !           689:        */
        !           690: 
        !           691:        // initialize virtual base pointers and virtual base objects
        !           692:        for (Pbcl l = cl->baselist; l; l=l->next) {
        !           693:                Pexpr i = l->init;
        !           694:                if (l->base != VIRTUAL) continue;
        !           695:                l->init = 0;
        !           696: //error('d',"simpl virtual base %t i %d ",l->bclass,i);
        !           697: 
        !           698:                // assign virtual OP to virtual base AP
        !           699:                Pclass bc = l->bclass;
        !           700:                Pexpr dp = 0;
        !           701: 
        !           702:                // dd = pointer argument for this base;
        !           703:                // non-zero if already initialized
        !           704:                for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list) 
        !           705:                        if (strcmp(dd->string,bc->string)==0) break;
        !           706: 
        !           707:                // initialize virtual base object
        !           708: //error('d',"bc %t dd %n offset %d init %d",bc,dd,l->obj_offset,l->init);
        !           709:                // => bc_arg = (bc*)((char*)this+offset)
        !           710:                int off = l->obj_offset;
        !           711:                Pexpr val = rptr(bc->this_type,th,off);
        !           712:                dp = new expr(ASSIGN,dd,val);
        !           713:                dd->assign();
        !           714: 
        !           715:                // => bc::bc()
        !           716:                if (i)  {
        !           717:                        switch (i->base) {
        !           718:                        case ASSIGN:
        !           719:                        case CM:
        !           720:                                break;
        !           721:                        case CALL:
        !           722:                        case G_CALL:
        !           723:                        {       Pcall cc = Pcall(i);
        !           724:                                Pname bn = cc->fct_name;
        !           725:                                ass_count = Pfct(bn->tp)->f_this->n_assigned_to;
        !           726:                                cc->simpl();
        !           727:                                break;
        !           728:                        }
        !           729:                        default:
        !           730:                                error('i',"badBCIr %k",i->base);
        !           731:                        }
        !           732:                        dp = new expr(CM,dp,i);
        !           733:                }
        !           734: 
        !           735:                // => (bc_arg==0)?dp:bc_arg
        !           736:                for (Pname a = f_args->n_list; a; a = a->n_list)
        !           737:                        if (strcmp(bc->string,a->string)==0) {
        !           738:                                dp = new expr(QUEST,dp,a);
        !           739:                                dp->cond = new expr(EQ,a,zero);
        !           740:                                break;
        !           741:                        }
        !           742: 
        !           743:                //      Pname dpp = find_vbase_ptr(bc,cl);
        !           744:                for (Pbcl ll=cl->baselist; ll; ll=ll->next) {
        !           745:                        if (ll->bclass==bc && ll->ptr_offset) {
        !           746:                                // make sure that the delegate_arg is needed
        !           747:                                // here and not just in a base
        !           748: 
        !           749:                                // this->Pd = (bc_arg==0)?dp:bc_arg
        !           750:                                Pexpr dpp = new mdot(bc->string,th);
        !           751:                                dpp->i1 = 3;
        !           752:                                dp = new expr(ASSIGN,dpp,dp);
        !           753: //error('d',"dpp %n",dpp);
        !           754:                                break;
        !           755:                        }
        !           756:                }
        !           757: 
        !           758:                // reverse init order
        !           759:                if (dp) init_list = init_list ? new expr(CM,dp,init_list) : dp;
        !           760:        }
        !           761: 
        !           762:        //      generate: this=base::base(args) (non-virtual bases)
        !           763: {      
        !           764:        for (Pbcl l = cl->baselist; l; l=l->next) {
        !           765:                Pexpr i = l->init;
        !           766:                if (i==0 || l->base==VIRTUAL) continue;
        !           767: //error('d',"simpl base %t i %d ",l->bclass,i);
        !           768:                l->init = 0;
        !           769:        
        !           770:                switch (i->base) {
        !           771:                case ASSIGN:
        !           772:                case CM:
        !           773:                        break;
        !           774:                case CALL:
        !           775:                case G_CALL:
        !           776:                {       Pcall cc = Pcall(i);
        !           777:                        Pname bn = cc->fct_name;
        !           778:                        ass_count = Pfct(bn->tp)->f_this->n_assigned_to;
        !           779:                        cc->simpl();
        !           780:                        // assign to ``this'' only from only base
        !           781:                        if (l==cl->baselist && cl->baselist->next==0) i = new expr(ASSIGN,th,cc);
        !           782:                        break;
        !           783:                }
        !           784:                default:
        !           785:                        error('i',"badBCIr %k",i->base);
        !           786:                }
        !           787: 
        !           788:                init_list = init_list ? new expr(G_CM,init_list,i) : i;
        !           789:        }
        !           790: }
        !           791: 
        !           792:        // initialize the vptrs that are updated by this class
        !           793: 
        !           794:         if (th) {
        !           795:            Pexpr ee = initialize_vptrs (cl, th);
        !           796:            if (ee)
        !           797:                init_list = init_list ? new expr(CM,init_list,ee) : ee;
        !           798:          }
        !           799: 
        !           800:         else {
        !           801:             error('i', "%t->fct::ctor_simpl(): th found to be null", cl);
        !           802:          }
        !           803: 
        !           804: 
        !           805:        // initialize members in declaration order:
        !           806:        int i;
        !           807:        for (Pname m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i) ) {
        !           808:                Ptype t = m->tp;
        !           809:                Pname cn;
        !           810:                Pname ctor;
        !           811:                if (t == 0) continue;
        !           812: 
        !           813:                switch (t->base) {
        !           814:                case FCT:
        !           815:                case OVERLOAD:
        !           816:                case CLASS:
        !           817:                case ENUM:
        !           818:                        continue;
        !           819:                }
        !           820: 
        !           821:                switch (m->n_stclass) {
        !           822:                case STATIC:
        !           823:                case ENUM:
        !           824:                        continue;
        !           825:                }
        !           826: 
        !           827:                if (m->base == PUBLIC) continue;
        !           828: 
        !           829:                Pexpr ee = m->n_initializer;
        !           830:                if (ee) m->n_initializer = 0;   // from fct must not persist until next fct
        !           831: //error('d',"simpl m %n ee %d",m,ee);
        !           832:                if (ee) {
        !           833:                        // init of non-class mem
        !           834:                        // set in fct::mem_init()
        !           835:                }
        !           836:                else if (cn=t->is_cl_obj()) {   // try for default
        !           837:                        Pclass cl = Pclass(cn->tp);
        !           838:                        if (ctor = cl->has_ictor()) {
        !           839:                                Pexpr r = new ref(REF,th,m);
        !           840:                                ee = call_ctor(tbl,r,ctor,0,DOT);
        !           841:        check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct);
        !           842:                        }
        !           843:                        else if (cl->has_ctor()) {
        !           844:                                error("M%n needsIr (no defaultK forC %s)",m,cl->string);
        !           845:                        }
        !           846:                }
        !           847:                else if (cl_obj_vec) {
        !           848:                        Pclass cl = Pclass(cl_obj_vec->tp);
        !           849:                        if (ctor = cl->has_ictor()) { // _new_vec(vec,noe,sz,ctor);
        !           850:                                Pexpr mm = new ref(REF,th,m);
        !           851:                                mm->tp = m->tp;
        !           852:                                ee = cdvec(vec_new_fct,mm,cl,ctor,-1,0);
        !           853:        check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct);
        !           854:                        }
        !           855:                        else if (cl->has_ctor()) {
        !           856:                                error("M%n[] needsIr (no defaultK forC %s)",m,cl->string);
        !           857:                        }
        !           858:                }
        !           859:                else if (t->is_ref()) {
        !           860:                        error("RM%n needsIr",m);
        !           861:                }
        !           862:                else if (t->tconst() && vec_const==0) {
        !           863:                        error("constM%n needsIr",m);
        !           864:                }
        !           865:        
        !           866:                if (ee) {
        !           867:                        ee->simpl();
        !           868:                        init_list = init_list ? new expr(CM,init_list,ee) : ee;
        !           869:                }
        !           870:        } // for m
        !           871: //error('d',"ctor->");
        !           872:        return ass_count;
        !           873: }
        !           874: 
        !           875: void fct::simpl()
        !           876: /*
        !           877:        call only for the function definition (body != 0)
        !           878: 
        !           879:        simplify argument initializers, and base class initializer, if any
        !           880:        then simplify the body, if any
        !           881: 
        !           882:        for constructor:call allocator if this==0 and this not assigned to
        !           883:                        (auto and static objects call constructor with this!=0,
        !           884:                        the new operator generates calls with this==0)
        !           885:                        call base & member constructors
        !           886:        for destructor: call deallocator (no effect if this==0)
        !           887:                        case base & member destructors
        !           888: 
        !           889:        for arguments and function return values look for class objects
        !           890:        that must be passed by constructor X(X&).
        !           891: 
        !           892:        Allocate temporaries for class object expressions, and see if
        !           893:        class object return values can be passed as pointers.
        !           894: 
        !           895:        call constructor and destructor for local class variables.
        !           896: */
        !           897: {
        !           898:        Pexpr th = f_this;
        !           899:        Ptable tbl = body->memtbl;
        !           900:        Pstmt ss = 0;
        !           901:        Pstmt tail;
        !           902:        Pclass cl = th ? Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp) : 0;
        !           903:        Pstmt dtail = 0;
        !           904: 
        !           905:        Pname ocurr_fct = curr_fct;
        !           906:        int oret = no_of_returns;
        !           907:        int oim = imeasure;
        !           908: 
        !           909: //error('d',"fct::simpl %n %t",curr_fct,this);
        !           910: //     not_inl = f_inline==0;
        !           911:        del_list = 0;
        !           912:        continue_del_list = 0;
        !           913:        break_del_list = 0;
        !           914:        scope = tbl;
        !           915:        if (scope == 0) error('i',"F::simpl()");
        !           916:        int ass_count = 0;
        !           917:        imeasure = 0;
        !           918:        no_of_returns = 0;
        !           919: 
        !           920:        cc->stack();
        !           921:        cc->nof = curr_fct;
        !           922:        cc->ftbl = tbl;
        !           923: 
        !           924: //      modification for local classes defined within inline functions
        !           925:        extern Plist local_class;
        !           926: // error( 'd', "simpl local_class: %d", local_class );
        !           927:        for ( Plist l = local_class; l; l = l->l ) {
        !           928:                Pname n = l->f; 
        !           929:                Pclass cl = Pclass(Pbase(n->tp)->b_name->tp);
        !           930:                if ( cl->in_fct == 0 ) cl->in_fct = cc->nof;
        !           931:                if ( cl->lcl == 0 ) cl->lcl = make_name( 'L' );
        !           932:                if ( cl->c_body == 1 ) cl->dcl_print(0);
        !           933:        }
        !           934: 
        !           935:        Pfct(cc->nof->tp)->local_class = local_class; 
        !           936:        local_class = 0;
        !           937: // error( 'd', "simpl nof: %n %d local_class: %d", cc->nof, cc->nof, Pfct(cc->nof->tp)->local_class );
        !           938: 
        !           939:        switch (curr_fct->n_scope) {
        !           940:        case 0:
        !           941:        case PUBLIC:
        !           942:                cc->not = curr_fct->n_table->t_name;
        !           943:                cc->cot = Pclass(cc->not->tp);
        !           944:                cc->tot = cc->cot->this_type;
        !           945:        }
        !           946: 
        !           947:        switch (curr_fct->n_oper) {
        !           948:        case  DTOR:
        !           949:                dtail = dtor_simpl(cl,th);
        !           950:                break;
        !           951:        case CTOR:
        !           952:                ass_count = ctor_simpl(cl,th);
        !           953:        }
        !           954: 
        !           955:        tail = body->simpl();
        !           956: 
        !           957:        if (returns->base!=VOID || f_result) {  // return must have been seen
        !           958:                if (no_of_returns) {            // could be OK
        !           959:                        Pstmt tt = (tail->base==RETURN || tail->base==LABEL) ? tail : trim_tail(tail);
        !           960: 
        !           961:                        switch (tt->base) {
        !           962:                        case RETURN:
        !           963:                        case GOTO:
        !           964:                                del_list = 0;   // no need for del_list
        !           965:                                break;
        !           966:                        case SM:
        !           967:                                if (tt->e)
        !           968:                                        switch (tt->e->base) {
        !           969:                                        case ICALL:
        !           970:                                        case G_CALL:
        !           971:                                                goto chicken;
        !           972:                                        }
        !           973:                        default:
        !           974:                                if (warning_opt || strcmp(curr_fct->string,"main"))     
        !           975:                                        error('w',"maybe no value returned from%n",curr_fct);
        !           976:                        case IF:
        !           977:                        case SWITCH:
        !           978:                        case DO:
        !           979:                        case WHILE:
        !           980:                        case FOR:
        !           981:                        case LABEL:
        !           982:                        chicken:                // don't dare write a warning
        !           983:                                break;
        !           984:                        }
        !           985:                }
        !           986:                else {  // must be an error
        !           987:                        // but we don't dare complain about main()
        !           988:                //      if (strcmp(curr_fct->string,"main"))
        !           989:                //              error(Pfct(curr_fct->tp)->returns->is_cl_obj()?0:'w',"no value returned from%n",curr_fct);
        !           990:                //      else if (warning_opt)   
        !           991:                //              error('w',"no value returned from%n",curr_fct);
        !           992:                        if (Pfct(curr_fct->tp)->f_inline
        !           993:                        && Pfct(curr_fct->tp)->returns!=void_type
        !           994:                        && Pfct(curr_fct->tp)->returns->is_cl_obj())
        !           995:                                // can cause code generation errors if allowed
        !           996:                                error("no value returned from%n",curr_fct);
        !           997:                        else if (warning_opt || strcmp(curr_fct->string,"main"))        
        !           998:                                error('w',"no value returned from%n",curr_fct);
        !           999:                }
        !          1000:                if (del_list) goto zaq;
        !          1001:        }
        !          1002:        else if (del_list) {    // return may not have been seen
        !          1003:        zaq:
        !          1004:                if (tail)
        !          1005:                        tail->s_list = del_list;
        !          1006:                else
        !          1007:                        body->s = del_list;
        !          1008:                tail = dtail;
        !          1009:        }
        !          1010: 
        !          1011:        if (curr_fct->n_oper == DTOR) { // body => if (this == 0) body
        !          1012: 
        !          1013: // reset the vptrs that were set by this class
        !          1014:        for (Pvirt blist = cl->virt_list; blist; blist = blist->next) {
        !          1015: //error('d',"vptr init %s in %s",blist->string,cl->string);
        !          1016:                topclass = cl;
        !          1017:                Pexpr vp = cl->get_vptr_exp(blist->string);
        !          1018: 
        !          1019: extern char *make_local_name(Pclass, int=0);
        !          1020:                 char *str = 0;
        !          1021:                 if ( cl->lex_level ) str = make_local_name( cl );
        !          1022:                 Pexpr vtbl = new text_expr(blist->string,str?str:cl->string);
        !          1023: 
        !          1024:                Pexpr ee = new ref(REF,th,vp);
        !          1025:                ee->tp = vp->tp;
        !          1026:                ee = new expr(ASSIGN,ee,vtbl);
        !          1027:                        Pstmt es = new estmt(SM,curloc,ee,0);
        !          1028:                        es->s_list = body->s;
        !          1029:                        body->s = es;
        !          1030:        }
        !          1031: 
        !          1032:                body->s = new ifstmt(body->where,th,body->s,0);
        !          1033:        }
        !          1034: 
        !          1035:        if (curr_fct->n_oper == CTOR) {
        !          1036: 
        !          1037:                if  (Pname(th)->n_assigned_to == 0) {
        !          1038:                /* generate:
        !          1039:                        if (this || (this=_new( sizeof(class cl) ))) {
        !          1040:                                init_list ;
        !          1041:                                body;
        !          1042:                        }
        !          1043:                */
        !          1044:                        Pname(th)->n_assigned_to = ass_count ? ass_count : FUDGE111;
        !          1045:                        Pexpr sz = new texpr(SIZEOF,cl,0);
        !          1046:                        (void) cl->tsizeof();
        !          1047:                        sz->tp = uint_type;
        !          1048:                        Pexpr ee = new expr(ELIST,sz,0);
        !          1049:                                Pname n = new name(oper_name(NEW));
        !          1050:                                Pexpr p = find_name(n,cl,scope,CALL,curr_fct);
        !          1051: //error('d',"in ctor %n call %n",curr_fct,p);
        !          1052:                                ee = new call(p,ee);
        !          1053:                                ee->tp = ee->call_fct(cl->memtbl);
        !          1054:                        ee->simpl();
        !          1055:                        ee = new expr(ASSIGN,th,ee);
        !          1056:                        ee = new expr(OROR,th,ee);
        !          1057:                        /*ifs->simpl();
        !          1058:                                do not simplify
        !          1059:                                or "this = " will cause an extra call of base::base
        !          1060:                        */
        !          1061:                        if (init_list) {
        !          1062:                                Pstmt es = new estmt(SM,body->where,init_list,0);
        !          1063:                                es->s_list = body->s;
        !          1064:                                body->s = es;
        !          1065:                        //      if (tail == 0) tail = es;
        !          1066:                        }
        !          1067:                        else if (body->s == 0)
        !          1068:                                body->s = new estmt(SM,body->where,0,0);
        !          1069:                        ifstmt* ifs = new ifstmt(body->where,ee,body->s,0);
        !          1070:                        body->s = ifs;
        !          1071:                //      if (tail == 0) 
        !          1072:                        tail = ifs;
        !          1073:                }
        !          1074:                // generate: body; return this;
        !          1075:                Pstmt st = new estmt(RETURN,curloc,th,0);
        !          1076:                if (tail)
        !          1077:                        tail->s_list = st;
        !          1078:                else
        !          1079:                        body->s = st;
        !          1080:                tail = st;
        !          1081:        }
        !          1082:        f_imeasure = imeasure;
        !          1083:        curr_fct = ocurr_fct;
        !          1084:        no_of_returns = oret;
        !          1085:        imeasure = oim;
        !          1086:        cc->unstack();
        !          1087: }
        !          1088: 
        !          1089: 
        !          1090: void classdef::simpl()
        !          1091: {
        !          1092:        int i;
        !          1093: //error('d',"classdef::simpl %s %d",string,defined&SIMPLIFIED);
        !          1094: 
        !          1095:        if (defined&SIMPLIFIED) return;
        !          1096: 
        !          1097:        Pclass oc = in_class;
        !          1098:        in_class = this;
        !          1099: 
        !          1100:        for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) {
        !          1101:                Pexpr i = m->n_initializer;
        !          1102:                m->n_initializer = 0;
        !          1103:                m->simpl();
        !          1104:                m->n_initializer = i;
        !          1105:        }
        !          1106: 
        !          1107:        in_class = oc;
        !          1108: 
        !          1109:        for (Plist fl=friend_list; fl; fl=fl->l) {      // simplify friends
        !          1110:                Pname p = fl->f;
        !          1111:                switch (p->tp->base) {
        !          1112:                case FCT:
        !          1113:                case OVERLOAD:
        !          1114:                        p->simpl();
        !          1115:                }
        !          1116:        }
        !          1117: 
        !          1118:        defined |= SIMPLIFIED;
        !          1119: }
        !          1120: 
        !          1121: 
        !          1122: 
        !          1123: 
        !          1124: Pexpr initialize_vptrs (Pclass cl, Pexpr this_expr)
        !          1125: 
        !          1126:     /* Constructs an expression which initializes the given class's vptrs.
        !          1127:        The this_expr forms the first part of the path expression for each
        !          1128:        vptr assignment. The vptr assignments are combined into a comma
        !          1129:        expression. */
        !          1130: 
        !          1131: {
        !          1132: 
        !          1133:     Pexpr init_list = 0;
        !          1134: 
        !          1135: 
        !          1136:     /* initialize the vptrs that are updated by this class */
        !          1137: 
        !          1138:     for (Pvirt blist = cl->virt_list; blist; blist = blist->next) {
        !          1139: 
        !          1140:        topclass = cl;
        !          1141:        Pexpr vptr_exp = cl->get_vptr_exp(blist->string);
        !          1142: 
        !          1143:        extern char *make_local_name(Pclass, int=0);
        !          1144:        char *str = 0;
        !          1145:        if ( cl->lex_level ) str = make_local_name(cl);
        !          1146:        Pexpr vtbl = new text_expr(blist->string,str?str:cl->string);
        !          1147: 
        !          1148:        Pexpr ee;
        !          1149:        if (this_expr)
        !          1150:            ee = new ref(REF, this_expr, vptr_exp);
        !          1151:        else
        !          1152:            ee = vptr_exp;
        !          1153: 
        !          1154:        ee->tp = vptr_exp->tp;
        !          1155:        ee = new expr(ASSIGN, ee, vtbl);
        !          1156:        init_list = init_list ? new expr(CM, init_list, ee) : ee;
        !          1157:       }
        !          1158:     
        !          1159:     return init_list;
        !          1160: 
        !          1161: } /* initialize_vptrs */

unix.superglobalmegacorp.com

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