Annotation of researchv10no/cmd/cfront/optcfront/expr3.c, revision 1.1

1.1     ! root        1: /*ident        "@(#)ctrans:src/expr3.c 1.7" */
        !             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: expr3.c:
        !            11: 
        !            12:        type check function calls, casts, and explicit coercions
        !            13: 
        !            14: ************************************************************************/
        !            15: 
        !            16: #include "cfront.h"
        !            17: #include "size.h"
        !            18: 
        !            19: int pr_dominate(Ptype t1, Ptype t2)
        !            20: /*
        !            21: */
        !            22: {
        !            23:        Pname cn1 = t1->is_cl_obj();
        !            24:        Pname cn2 = t2->is_cl_obj();
        !            25: //error('d',"pr_dominate(%t,%t)",t1,t2);
        !            26: 
        !            27:        if (cn1==0 || cn2==0) {
        !            28:                Ptype p1 = t1->is_ptr();
        !            29:                Ptype p2 = t2->is_ptr();
        !            30:                if (p1 && p2) {                 // pointers
        !            31:                        cn1 = Pptr(p1)->typ->is_cl_obj();
        !            32:                        cn2 = Pptr(p2)->typ->is_cl_obj();
        !            33:                        if (cn1==0 || cn2==0) return 0;
        !            34:                }
        !            35:                else {
        !            36:                        p1 = t1->is_ref();
        !            37:                        p2 = t2->is_ref();
        !            38:                        if (p1 && p2) {         // references
        !            39:                                cn1 = Pptr(p1)->typ->is_cl_obj();
        !            40:                                cn2 = Pptr(p2)->typ->is_cl_obj();
        !            41:                                if (cn1==0 || cn2==0) return 0;
        !            42:                        }
        !            43:                //      else if (p1 && cn2) {
        !            44:                //              cn1 = Pptr(p1)->typ->is_cl_obj();
        !            45:                //      }
        !            46:                        else
        !            47:                                return 0;       // not the same and not classes
        !            48:                }
        !            49:        }
        !            50:        Pclass c1 = Pclass(cn1->tp);
        !            51:        Pclass c2 = Pclass(cn2->tp);
        !            52: //error('d'," c1 : c2 %d; c2 : c1 %d",c1->has_base(c2),c2->has_base(c1));
        !            53:        if (c1->has_base(c2)) return 1;
        !            54:        if (c2->has_base(c1)) return 2;
        !            55:        return 0;
        !            56: }
        !            57: 
        !            58: int exact1(Pname,Ptype);
        !            59: static exact2(Pname,Ptype);
        !            60: static exact3(Pname,Ptype);
        !            61: 
        !            62: static Pname user_dominate(Pname n1, Pname n2, Pexpr arg)
        !            63: {
        !            64:        Pfct f1 = Pfct(n1->tp);
        !            65:        Pfct f2 = Pfct(n2->tp);
        !            66: 
        !            67:        Pname a1 = f1->argtype;
        !            68:        Pname a2 = f2->argtype;
        !            69: //error('d',"user_dominate: %n %t %t",n1,f1,f2);
        !            70: 
        !            71:        for(; a1 && a2; a1 = a1->n_list, a2 = a2->n_list) {
        !            72:                Ptype t1 = a1->tp;
        !            73:                Ptype t2 = a2->tp;
        !            74:        }
        !            75: 
        !            76:        if (a1 && !a1->n_evaluated) return n1;
        !            77:        if (a2 && !a2->n_evaluated) return n2;
        !            78: 
        !            79:        a1 = f1->argtype;
        !            80:        a2 = f2->argtype;
        !            81: 
        !            82:        Pname prev = 0;
        !            83:        Pexpr e = arg;
        !            84: 
        !            85:        for(; a1 && a2 && e; a1 = a1->n_list, a2 = a2->n_list, e = e->e2) {
        !            86:                Ptype t1 = a1->tp;
        !            87:                Ptype t2 = a2->tp;
        !            88:                Ptype at = e->e1->tp;
        !            89: 
        !            90:                int j = can_coerce(t1,at);
        !            91:                Ptype tt1 = Ncoerce ? Pfct(Ncoerce->tp)->returns : 0;
        !            92:                j = can_coerce(t2,at);
        !            93:                Ptype tt2 = Ncoerce ? Pfct(Ncoerce->tp)->returns : 0;
        !            94:                if(!tt1 || !tt2 || tt1->check(tt2,OVERLOAD)) 
        !            95:                        return 0;
        !            96: 
        !            97:                int one = 0, two = 0;
        !            98:                if(exact1(a1,tt1)) one = 4;
        !            99:                else if(exact2(a1,tt1)) one = 3;
        !           100:                else if(exact3(a1,tt1)) one = 2;
        !           101:                else one = 1;
        !           102:                if(exact1(a2,tt1)) two = 4;
        !           103:                else if(exact2(a2,tt1)) two = 3;
        !           104:                else if(exact3(a2,tt1)) two = 2;
        !           105:                else two = 1;
        !           106: 
        !           107:                if(one > two && (!prev || prev==n1)) prev = n1;
        !           108:                else if(two > one && (!prev || prev==n2)) prev = n2;
        !           109:                else if(one == two && one) ;
        !           110:                else return 0;
        !           111:        }
        !           112:        if(prev) return prev;
        !           113:        
        !           114:        return 0;
        !           115: }
        !           116: 
        !           117: Pname dominate(Pname n1, Pname n2, Pexpr arg, int const_obj, int level)
        !           118: /*
        !           119:        the two functions n1 and n2 can each respond to a call using
        !           120:        standard conversions. Does the one dominate the other in the
        !           121:        sense that all its arguments are identical to the other or
        !           122:        classes defived from the class of the corresponding argument
        !           123:        of the other.
        !           124: 
        !           125:        If so return it, otherwise return 0;
        !           126: */
        !           127: {
        !           128:        Pname res = 0;
        !           129: 
        !           130:        Pfct f1 = Pfct(n1->tp);
        !           131:        Pfct f2 = Pfct(n2->tp);
        !           132: 
        !           133:        Pname a1 = f1->argtype;
        !           134:        Pname a2 = f2->argtype;
        !           135:        Pexpr e = arg;
        !           136: //error('d',"dominate: %n %t %t e %d",n1,f1,f2,e);
        !           137: 
        !           138:        if (e == 0) {
        !           139:                if (const_obj) {
        !           140:                        if (f1->f_const && f2->f_const==0) return n1;
        !           141:                        if (f2->f_const && f1->f_const==0) return n2;
        !           142:                }
        !           143:                else {
        !           144:                        if (f1->f_const==0 && f2->f_const) return n1;
        !           145:                        if (f2->f_const==0 && f1->f_const) return n2;
        !           146:                }
        !           147:                return 0;
        !           148:        }
        !           149: 
        !           150:        for(; a1 && a2 && e; a1 = a1->n_list, a2 = a2->n_list, e = e->e2) {
        !           151:                Ptype t1 = a1->tp;
        !           152:                Ptype t2 = a2->tp;
        !           153:                Ptype at = e->e1->tp;
        !           154: //error('d',"t1 %t t2 %t at %t",t1,t2,at);
        !           155:                if (t1==t2 || t1->check(t2,0)==0 )
        !           156:                        continue;
        !           157:                Pptr r1 = t1->is_ref();
        !           158:                Pptr r2 = t2->is_ref();
        !           159: //error('d',"const_problem %t %t %t %d",t1,t2,at,const_problem);
        !           160:                if (const_problem) {    // t1 and t1 differs only in const
        !           161:                        Pname rr;
        !           162:                        if (at->check(t1,0)==0 && const_problem==0) {
        !           163:                                if (t1->is_ptr())
        !           164:                                        rr = n1;
        !           165:                                else
        !           166:                                        goto nc;
        !           167:                        }
        !           168:                        else if (at->check(t2,0)==0 && const_problem==0) {
        !           169:                                if (t2->is_ptr())
        !           170:                                        rr = n2;
        !           171:                                else
        !           172:                                        goto nc;
        !           173:                        }
        !           174:                        else if (r1 && r1->typ->check(at,0)==0 && const_problem==0)
        !           175:                                rr = n1;
        !           176:                        else if (r2 && r2->typ->check(at,0)==0 && const_problem==0)
        !           177:                                rr = n2;
        !           178:                        else
        !           179:                                goto nc;
        !           180:                
        !           181:                        if (res && res!=rr) return 0;   // mutual dominace
        !           182:                        res = rr;
        !           183:                        continue;       // identical
        !           184:                }
        !           185:        nc:
        !           186:                if (r2 && (t1==r2 || t1->check(r2->typ,0)==0)) continue;
        !           187:                if (r1 && (t2==r1 || t2->check(r1->typ,0)==0)) continue;
        !           188: 
        !           189:                Pname rr = 0;
        !           190:                if (t1==at || exact1(a1,at)) {
        !           191:                        rr = n1;
        !           192:                        if (t2==at || exact1(a2,at))
        !           193:                                continue;
        !           194:                }
        !           195:                else if (t2==at || exact1(a2,at))
        !           196:                        rr = n2;
        !           197:                else if (1<level) {     // try integral promotion
        !           198:                        if (exact2(a1,at))
        !           199:                                rr = n1;
        !           200:                        if (exact2(a2,at)) {
        !           201:                                if (rr) rr = 0;
        !           202:                                else rr = n2;
        !           203:                        }
        !           204:                }
        !           205:                if (!rr && 2<level) {   // try standard conversions
        !           206:                        if (exact3(a1,at))
        !           207:                                rr = n1;
        !           208:                        if (exact3(a2,at)) {
        !           209:                                if (rr) rr = 0;
        !           210:                                else rr = n2;
        !           211:                        }
        !           212:                }
        !           213:                if (rr) {
        !           214:                        if  (res && res!=rr) return 0;  // mutual dominance
        !           215:                        res = rr;
        !           216:                        continue;
        !           217:                }
        !           218: 
        !           219:                int r = pr_dominate(t1,t2);
        !           220: //error('d',"pr1 %d",r);
        !           221:                if (r) {
        !           222:                        Pname rr = r==1?n1:n2;
        !           223:                        if (res && res!=rr) return 0;   // mutual dominace
        !           224:                        res = rr;
        !           225:                        continue;
        !           226:                }
        !           227: 
        !           228:                r = pr_dominate(t1,at);
        !           229: //error('d',"pr2 %d",r);
        !           230:                if (r==2) {
        !           231:                        if (res && res!=n1) return 0;   // mutual dominace
        !           232:                        res = n1;
        !           233:                        r = pr_dominate(t2,at);
        !           234:                        if (r==2) return 0;     // mutual dominace
        !           235:                        continue;
        !           236:                }
        !           237: 
        !           238:                r = pr_dominate(t2,at);
        !           239: //error('d',"pr3 %d",r);
        !           240:                if (r==2) {
        !           241:                        if (res && res!=n2) return 0;   // mutual dominace
        !           242:                        res = n2;
        !           243:                        continue;
        !           244:                }
        !           245: 
        !           246:        }
        !           247:        //if (a1==0 && a2 && a2->n_initializer==0) return 0;    // wrong number of arguments
        !           248:        //if (a2==0 && a1 && a1->n_initializer==0) return 0;    // wrong number of arguments
        !           249: 
        !           250:        if (e) {
        !           251: //error('d',"more args %t a1 %t a2 %t",e->e1->tp,a1?a1->tp:0,a2?a2->tp:0);
        !           252:                int k1 = f1->nargs_known!=ELLIPSIS;
        !           253:                int k2 = f2->nargs_known!=ELLIPSIS;
        !           254:                if (a1 && a1->tp->check(e->e1->tp,ASSIGN)==0) return n1;
        !           255:                if (a2 && a2->tp->check(e->e1->tp,ASSIGN)==0) return n2;
        !           256:                if (k1 && k2) return 0;
        !           257:        }
        !           258: 
        !           259:        if (a1==0 && a2 && a2->n_initializer==0) return 0;
        !           260:        if (a2==0 && a1 && a1->n_initializer==0) return 0;
        !           261:        if (res==0)
        !           262:                if (const_obj) {
        !           263:                        if (f1->f_const && f2->f_const==0) return n1;
        !           264:                        if (f2->f_const && f1->f_const==0) return n2;
        !           265:                }
        !           266:                else {
        !           267:                        if (f1->f_const==0 && f2->f_const) return n1;
        !           268:                        if (f2->f_const==0 && f1->f_const) return n2;
        !           269:                }
        !           270: //error('d'," -> %n %t",res,res?res->tp:0);
        !           271:        return res;
        !           272: }
        !           273: 
        !           274: Pname Ntmp;
        !           275: 
        !           276: static refd;   // initialization routine called by ref_init, do not apply itor
        !           277: static no_sti;
        !           278: extern int stat_init;
        !           279: 
        !           280: Pname make_tmp(char c, Ptype t, Ptable tbl)
        !           281: {
        !           282:        int dt = 0; 
        !           283:        Pname tn = tbl->t_name;
        !           284:        Pname cn = t->is_cl_obj();
        !           285: 
        !           286:        if (tn && tn->tp) error('s',"defaultA too complicated");
        !           287:        if (cn && Pclass(cn->tp)->has_dtor()) dt = 1;
        !           288:        if (Ntmp == 0 && dt ) Ntmp = cn;
        !           289: 
        !           290: //error('d',"tbl %d cstmt %d %d sti %d",tbl,Cstmt,Cstmt?Cstmt->memtbl:0,sti_tbl);
        !           291:        if (Cstmt) {    //      make Cstmt into a block
        !           292:                if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0);
        !           293:                tbl = Cstmt->memtbl;
        !           294:        }
        !           295:        else if (tbl == gtbl && no_sti == 0) {
        !           296:                if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0);
        !           297:                tbl = sti_tbl;
        !           298:        }
        !           299: 
        !           300:        Pname tmpx = new name(make_name(c));
        !           301:        tmpx->where = no_where;
        !           302:        tmpx->tp = t;
        !           303:        (void) t->tsizeof();
        !           304:        if ( t->base == COBJ ) {
        !           305:                Pclass cl = Pclass(Pbase(t)->b_name->tp);
        !           306:                if ( cl->lex_level ) tmpx->lex_level = cl->lex_level;
        !           307:        }
        !           308: 
        !           309:        TOK scop = ARG;
        !           310:        if (stat_init && dt) { 
        !           311:                tmpx->n_sto = STATIC; scop = ARGS; 
        !           312:        }
        !           313: 
        !           314:        // ARG[S]: no init; ARGS: static dtor
        !           315:        Pname tmp = tmpx->dcl(tbl,scop); 
        !           316:        delete tmpx;
        !           317: 
        !           318:        // n_scope == ARGS sets static dtor in simpl2.c
        !           319:        tmp->n_scope = (scop==ARG) ? FCT : ARGS;
        !           320:        return tmp;
        !           321: }
        !           322: 
        !           323: Pexpr init_tmp(Pname tmp, Pexpr init, Ptable tbl)
        !           324: {
        !           325:        Pname cn = tmp->tp->is_cl_obj();
        !           326:        Pname ct = cn ? Pclass(cn->tp)->has_itor() : 0;
        !           327: 
        !           328:        tmp->n_assigned_to = 1;
        !           329: //error('d',"init_tmp %n ct %n refd %d",tmp,ct,refd);
        !           330:        if (ct) {       // must initialize
        !           331:                if (refd) {
        !           332: //error('d',"'orrible %k",init->e1->base);
        !           333:                        switch (init->e1->base) {       // 'orrible 'ack
        !           334:                        case NAME:
        !           335:                        case REF:
        !           336:                        case DEREF:
        !           337:                                if (init->e1->tp->is_ptr())
        !           338:                                        init = init->e1;
        !           339:                                else
        !           340:                                        init = new expr(G_CM,init,init->e1->address());
        !           341:                                        
        !           342:                        }
        !           343:                        if (ct->tp->base == OVERLOAD) ct = Pgen(ct->tp)->fct_list->f;   // first fct
        !           344:                        tbl = 0;
        !           345:                }
        !           346:                return call_ctor(tbl,tmp,ct,init,DOT);
        !           347:        }
        !           348:        Pexpr ass = new expr(ASSIGN,tmp,init); // no ctor: can assign
        !           349:        ass->tp = tmp->tp;
        !           350:        return ass;
        !           351: }
        !           352: /*
        !           353: int exact0(Pname nn, Ptype at)
        !           354: //     return 1 if
        !           355: //     exact match
        !           356: 
        !           357: {
        !           358:        if (nn == 0) return 0; //known==ELLIPSIS;
        !           359:        Ptype nt = nn->tp;
        !           360:        if (at == nt) return 1;
        !           361: //error('d',"exact0 %d",nt->check(at,0));
        !           362:        return nt->check(at,0)==0;
        !           363: }
        !           364: */
        !           365: 
        !           366: int exact3(Pname nn, Ptype at)
        !           367: /*
        !           368:        return 1 if
        !           369:        match with standard conversions
        !           370: */
        !           371: {
        !           372:        if (nn == 0) return 0; //known==ELLIPSIS;
        !           373:        Ptype nt = nn->tp;
        !           374: 
        !           375:        while(nt->base == TYPE)
        !           376:                nt = Pbase(nt)->b_name->tp;
        !           377: 
        !           378:        if (at == nt) return 1;
        !           379: 
        !           380:        switch (nt->base) {
        !           381:        case RPTR:
        !           382:                if (at==zero_type && Pptr(nt)->typ->is_ptr()==0) return 0; //break;
        !           383:                if (nt->check(at,COERCE)) {
        !           384:                        Pptr pt = at->addrof();
        !           385:                        nt->base = PTR;         // handle derived classes
        !           386:                        if (nt->check(pt,COERCE)) {
        !           387:                                nt->base = RPTR;
        !           388:                                delete pt;
        !           389:                                return 0;
        !           390:                        }
        !           391:                        nt->base = RPTR;
        !           392:                        delete pt;
        !           393:                }
        !           394:                break;
        !           395:        default:
        !           396:                switch (at->base) {
        !           397:                default: 
        !           398:                        if (nt->check(at,COERCE)) return 0;
        !           399:                        break;
        !           400:                case OVERLOAD:
        !           401:                        // the actual argument is an overloaded function
        !           402:                        // we'll try each instance until one matches
        !           403:                        register Plist gl;
        !           404:                        int no_match = 1;
        !           405: 
        !           406:                        for (gl = Pgen(at)->fct_list; gl; gl=gl->l) {
        !           407:                                if (nt->check(gl->f->tp,COERCE)==0) {
        !           408:                                        no_match = 0;
        !           409:                                        break;
        !           410:                                }
        !           411:                        }
        !           412: 
        !           413:                        if ( no_match ) return 0;
        !           414:                } 
        !           415:        }
        !           416:        return 1;
        !           417: }
        !           418: 
        !           419: int exact1(Pname nn, Ptype at)
        !           420: /*
        !           421:        return 1 if
        !           422:        exact match with
        !           423:                T <-> const T
        !           424:                X -> X&
        !           425:                T* -> const T*
        !           426:                T* -> T*const
        !           427:        taken into account
        !           428: */
        !           429: {
        !           430:        if (nn == 0) return 0;//known==ELLIPSIS;
        !           431:        Ptype nt = nn->tp;
        !           432:        if (at == nt) return 1;
        !           433: 
        !           434: //error('d',"exact1 nt %t at %t",nt,at);
        !           435:        if (nt->check(at,0)) {
        !           436: //error('d',"nt %t at %t cp %d",nt,at,const_problem);
        !           437:                if (const_problem)  return 1;   // handle T <-> const T
        !           438: 
        !           439:                Pptr rt = nt->is_ref(); //handle X -> X&
        !           440:                if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem))  return 1;
        !           441: 
        !           442:                Pptr art = at->is_ptr();
        !           443:                if (rt && art) return 0; // ptrs do not match refs
        !           444: 
        !           445:                // handle T* -> const T* and
        !           446:                // T* -> T*const
        !           447:                if (rt || (rt = nt->is_ptr())) {
        !           448:                        if (art == 0) art = at->is_ref();
        !           449:                        if (art) {
        !           450: //error('d',"art %t %t",art->typ,rt->typ);
        !           451:                                if (art->typ->check(rt->typ,0)) {
        !           452:                                        if (const_problem)  return 1;
        !           453:                                }
        !           454:                                else    // T* -> T*const
        !           455:                                         return 1;
        !           456:                        }
        !           457:                }
        !           458:                return 0;
        !           459:        }
        !           460:        return 1;
        !           461: }
        !           462: 
        !           463: Pexpr Ninit;   // default argument used;
        !           464: int Nstd;      // standard coercion used (derived* =>base* or int=>long or ...)
        !           465: 
        !           466: bit exact_match(Pname n, Pexpr arg)
        !           467: /*
        !           468:        look for an exact match between "n" and the argument list "arg"
        !           469:        This function goes through three stages:
        !           470:        (1) exact match (no coercions at all)
        !           471:        (2) do integral promotions and float->double and re-try exact match
        !           472:        (3) try for unique standard conversions
        !           473: 
        !           474: */
        !           475: {
        !           476:        Pfct f = Pfct(n->tp);
        !           477:        register Pexpr e;
        !           478:        register Pname nn;
        !           479: 
        !           480: // error('d',"exact_match(%n) %t",n,n->tp);
        !           481: 
        !           482:        for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
        !           483:                Pexpr a = e->e1;
        !           484:                Ptype at = a->tp;
        !           485:                if (at->base == ANY) return 0;
        !           486:                if (at->base == ZTYPE) at = int_type;
        !           487:                if (exact1(nn,at)==0) return 0;
        !           488:        }
        !           489: 
        !           490: //error('d',"exact %d -> %d",nn,nn?nn->n_initializer!=0:1);
        !           491:        if (nn) {
        !           492:                Ninit = nn->n_initializer;
        !           493:                return Ninit!=0;
        !           494:        }
        !           495: 
        !           496: //error('d',"return 1");
        !           497:        return 1;       // exact match without any promotions
        !           498: }
        !           499: 
        !           500: int exact2(Pname nn, Ptype at)
        !           501: /*
        !           502:        return 1 if
        !           503:        do integral promotion and float->double on at, then match
        !           504: */
        !           505: {
        !           506: //error('d',"exact2 nt %t at %t",nn?nn->tp:0,at);
        !           507:        while(at->base == TYPE)
        !           508:                at = Pbase(at)->b_name->tp;
        !           509: 
        !           510:        switch (at->base) {
        !           511:        case EOBJ:
        !           512:                at = Penum(Pbase(at)->b_name->tp)->e_type;
        !           513:                break;
        !           514:        case ZTYPE:
        !           515:                at = int_type;
        !           516:                break;
        !           517:        case CHAR:
        !           518:        case SHORT:
        !           519:                at = (Pbase(at)->b_unsigned && at->tsizeof()==SZ_INT) ? uint_type : int_type;
        !           520:                break;
        !           521:        case FLOAT:
        !           522:                at = double_type;
        !           523:        }
        !           524: 
        !           525:        if (nn == 0) return 0;//known==ELLIPSIS;
        !           526:        Ptype nt = nn->tp;
        !           527: //error('d',"  exact2 nt %t at %t",nt,at);
        !           528:        if (at == nt) return 1;
        !           529:        if (nt->check(at,0)) {
        !           530:                if (const_problem) return 1;
        !           531: 
        !           532:                Pptr rt = nt->is_ref(); // handle X -> X&
        !           533:                if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem)) return 1;
        !           534: 
        !           535:                Pptr art = at->is_ptr();
        !           536:                if (rt && art) return 0; // ptrs do not match refs
        !           537: 
        !           538:                // handle T* -> const T* and
        !           539:                // T* -> T*const
        !           540:                if (rt || (rt = nt->is_ptr())) {
        !           541:                        if (art == 0) art = at->is_ref();
        !           542:                        if (art) {
        !           543:                                if (art->typ->check(rt->typ,0)) {
        !           544:                                        if (const_problem) return 1;
        !           545:                                }
        !           546:                                else    // T* -> T*const
        !           547:                                        return 1;
        !           548:                        }
        !           549:                }
        !           550:                return 0;
        !           551:        }
        !           552:        return 1;
        !           553: }
        !           554: 
        !           555: bit prom_match(Pname n, Pexpr arg)
        !           556: /*
        !           557:        look for an exact match between "n" and the argument list "arg"
        !           558:        using integral promotions and float->double
        !           559: 
        !           560: */
        !           561: {
        !           562:        Pfct f = Pfct(n->tp);
        !           563:        register Pexpr e;
        !           564:        register Pname nn;
        !           565: 
        !           566: // error('d',"prom_match(%n) %t",n,n->tp);
        !           567: 
        !           568:        for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
        !           569:                Pexpr a = e->e1;
        !           570:                Ptype at = a->tp;
        !           571:                if (at->base == ANY) return 0;
        !           572: 
        !           573:                if (exact2(nn,at)==0) return 0;
        !           574:        }
        !           575:        
        !           576:        if (nn) {
        !           577:                Ninit = nn->n_initializer;
        !           578:                return Ninit!=0;
        !           579:        }
        !           580: 
        !           581:        return 1;       // exact match with promotions
        !           582: }
        !           583: 
        !           584: bit std_match(Pname n, Pexpr arg)
        !           585: /*
        !           586:        look for an exact match between "n" and the argument list "arg"
        !           587:        using standard conversions
        !           588: 
        !           589: */
        !           590: {
        !           591:        Pfct f = Pfct(n->tp);
        !           592:        register Pexpr e;
        !           593:        register Pname nn;
        !           594: 
        !           595: // error('d',"std_match(%n) %t",n,n->tp);
        !           596: 
        !           597:        for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
        !           598:                Pexpr a = e->e1;
        !           599:                Ptype at = a->tp;
        !           600: 
        !           601:                if (at->base == ANY) return 0;
        !           602:                if ( exact3(nn,at) == 0) return 0;
        !           603:        }
        !           604: 
        !           605:        if (nn) {
        !           606:                Ninit = nn->n_initializer;
        !           607:                return Ninit!=0;
        !           608:        }
        !           609: 
        !           610:        return 1;
        !           611: }
        !           612: 
        !           613: Pname Ncoerce;
        !           614: int ref_cast;
        !           615: 
        !           616: bit can_coerce(Ptype t1, Ptype t2)
        !           617: /*     return number of possible coercions of t2 into t1,
        !           618:        Ncoerce holds a coercion function (not constructor), if found
        !           619: */
        !           620: {
        !           621:        int zz = 0;
        !           622:        Ncoerce = 0;
        !           623:        if (t2->base == ANY) return 0;
        !           624: // error('d',"can_coerce t1 %t t2 %t",t1, t2);
        !           625: 
        !           626:        while(t1->base == TYPE)
        !           627:                t1 = Pbase(t1)->b_name->tp;
        !           628: 
        !           629:        switch (t1->base) {
        !           630:        case RPTR:
        !           631:                while(t2->base == TYPE)
        !           632:                        t2 = Pbase(t2)->b_name->tp;
        !           633: 
        !           634:                switch (t2->base) {
        !           635:        //      case VEC:
        !           636:        //      case PTR:
        !           637:        //      case RPTR:
        !           638:        //              if (t1->check(t2,COERCE) == 0) return 1;
        !           639:                default:        
        !           640:                {       Ptype tt2 = t2->addrof();
        !           641:                        if (t1->check(tt2,COERCE) == 0) return 1;
        !           642:                        if (ref_cast) break;//return 0; // (T&): no coercions
        !           643:                                                        // except operator T&()
        !           644:                        Ptype tt1 = Pptr(t1)->typ;
        !           645:                        while (tt1->base==TYPE) tt1 = Pbase(tt1)->b_name->tp;
        !           646:                        int bc;
        !           647:                        if ( tt1->base != PTR && tt1->base != RPTR ) {
        !           648:                                bc = Pbase(tt1)->b_const;
        !           649:                                Pbase(tt1)->b_const = 0; 
        !           650:                        }
        !           651:                        int i = can_coerce(tt1,t2);
        !           652:                        if ( tt1->base != PTR && tt1->base != RPTR ) 
        !           653:                                Pbase(tt1)->b_const = bc;
        !           654:                        if (i) return i;
        !           655:                        zz = 1;
        !           656:                }
        !           657:                }
        !           658:        }
        !           659: 
        !           660:        Pname c1 = t1->is_cl_obj();
        !           661:        Pname c2 = t2->is_cl_obj();
        !           662:        int val = 0;
        !           663:        if (ref_cast || zz) goto oper_coerce;
        !           664:        if (c1) {
        !           665:                Pclass cl = Pclass(c1->tp);
        !           666:                if (c2 && c2->tp==cl) return 1;
        !           667: 
        !           668:                 // A more comprehensive test for template classes
        !           669:                 if (c2 && (Pclass(c1->tp)->same_class(Pclass(c2->tp))))
        !           670:                         return 1 ;
        !           671: 
        !           672:                /*      look for constructor
        !           673:                                with one argument
        !           674:                                or with default for second argument
        !           675:                        of acceptable type
        !           676:                */
        !           677:                Pname ctor = cl->has_ctor();
        !           678:                if (ctor == 0) goto oper_coerce;
        !           679:                register Pfct f = Pfct(ctor->tp);
        !           680: //error('d',"ctor %n f %t",ctor,f);
        !           681:                switch (f->base) {
        !           682:                case FCT:
        !           683:                        switch (f->nargs) {
        !           684:                        case 1:
        !           685:                        one:
        !           686:                        {       Ptype tt = f->argtype->tp;
        !           687:                                        if (tt->check(t2,COERCE)==0)
        !           688:                                                val = 1;
        !           689:                                        else if (const_problem) {
        !           690:                                                Pptr p1 = tt->is_ptr_or_ref();
        !           691:                                                if (p1==0 || p1->typ->tconst()) val = 1;
        !           692:                                        }
        !           693:                                if (tt = tt->is_ref()) {
        !           694:                                        Pptr pt = t2->addrof(); // handle derived classed
        !           695:                                        tt->base = PTR;
        !           696:                                        if (tt->check(pt,COERCE) == 0) val = 1;
        !           697:                                        tt->base = RPTR;
        !           698:                                        delete pt;
        !           699:                                }
        !           700:                                goto oper_coerce;
        !           701:                        }
        !           702:                        default:
        !           703:                                if (f->argtype->n_list->n_initializer) goto one;
        !           704:                        case 0:
        !           705:                                goto oper_coerce;
        !           706:                        }
        !           707:                case OVERLOAD:
        !           708:                {       register Plist gl;
        !           709: 
        !           710:                        for (gl=Pgen(f)->fct_list; gl; gl=gl->l) { // look for match
        !           711:                                Pname nn = gl->f;
        !           712:                                Pfct ff = Pfct(nn->tp);
        !           713: 
        !           714:                                switch (ff->nargs) {
        !           715:                                case 0:
        !           716:                                        break;
        !           717:                                case 1:
        !           718:                                over_one:
        !           719:                                {       Ptype tt = ff->argtype->tp;
        !           720: //error('d',"over one %t %t -> %d %d",tt,t2,tt->check(t2,COERCE),const_problem);
        !           721:                                        if (tt->check(t2,COERCE)==0)
        !           722:                                                val = 1;
        !           723:                                        else if (const_problem) {
        !           724:                                                Pptr p1 = tt->is_ptr_or_ref();
        !           725:                                                if (p1==0 || p1->typ->tconst()) val = 1;
        !           726:                                        }
        !           727:                                        if (tt=tt->is_ref()) {
        !           728:                                                Pptr pt = t2->addrof(); // handle derived classed
        !           729:                                                tt->base = PTR;
        !           730:                                                if (tt->check(pt,COERCE) == 0) {
        !           731:                                                        tt->base = RPTR;
        !           732:                                                        delete pt;
        !           733:                                                        val = 1;
        !           734:                                                        goto oper_coerce;
        !           735:                                                }
        !           736:                                                tt->base = RPTR;
        !           737:                                                delete pt;
        !           738:                                        }
        !           739:                                        break;
        !           740:                                }
        !           741:                                default:
        !           742:                                        if (ff->argtype->n_list->n_initializer) goto over_one;
        !           743:                                }
        !           744:                        }
        !           745:                        goto oper_coerce;
        !           746:                }
        !           747:                default:
        !           748:                        error('i',"cannot_coerce(%k)\n",f->base);
        !           749:                }
        !           750:        }
        !           751: 
        !           752: oper_coerce:
        !           753: //error('d',"oper_coerce %d",val);
        !           754:        if (c2) {       
        !           755:                Pclass cl = Pclass(c2->tp);
        !           756:                int std = 0;
        !           757:                int oval = val;
        !           758:                extern Pname conv_dominates(Pname,Pname);
        !           759:                for (Pname ox, on=cl->conv; on; on=ox) {
        !           760:                        ox = on->n_list;
        !           761: // error( 'd', "can_coerce: ox: %s on: %s tp: %k", ox?ox->string:"", on->string, on->tp->base );
        !           762:                        Plist gl = 0;
        !           763:                        if ( on->tp->base == OVERLOAD ) {
        !           764:                                gl = Pgen(on->tp)->fct_list;
        !           765:                                on = gl->f;
        !           766:                                gl = gl->l;
        !           767:                        }
        !           768: 
        !           769: overlist: 
        !           770: // error( 'd', "can coerce: on: %n tp: %t gl: %d", on, on->tp, gl );
        !           771: 
        !           772:                        Pfct f = Pfct(on->tp);
        !           773:                        Nstd = 0;
        !           774:                        if (t1->check(f->returns,COERCE) == 0) {
        !           775:                                if (Nstd==0) {  // forget solutions involving standard conversions
        !           776:                                        Pname old = Ncoerce;
        !           777:                                        if (std) {      // forget
        !           778:                                                val = oval+1;
        !           779:                                                std = 0;
        !           780:                                                Ncoerce = on;
        !           781:                                        }
        !           782:                                        else if (Ncoerce == 0) {
        !           783:                                        //      val = 1;
        !           784:                                                val++;
        !           785:                                                Ncoerce = on;
        !           786:                                        }
        !           787:                                        else if ((Ncoerce = conv_dominates(Ncoerce,on))==0) {
        !           788:                                                if (val == 1) {
        !           789: //error('d',"val==1 on %n old %n",on,old);
        !           790:                                                        Ptype ton = Pfct(on->tp)->returns;
        !           791:                                                        Ptype tco = Pfct(old->tp)->returns;
        !           792:                                                        if (t1->check(ton,0)==0)
        !           793:                                                                ;
        !           794:                                                        else if (t1->check(tco,0)==0)
        !           795:                                                                on = old;
        !           796:                                                        else
        !           797:                                                                val++;
        !           798:                                                }
        !           799:                                                else
        !           800:                                                        val++;
        !           801:                                                Ncoerce = on;
        !           802:                                        }
        !           803:                                }
        !           804:                                else {  // take note only if no exact match seen
        !           805:                                        if (Ncoerce==0 || on->tp->check(Ncoerce->tp,0)) {
        !           806:                                                if (val==0 || std) {
        !           807: 
        !           808:                                                        if (Ncoerce) Ncoerce = conv_dominates(Ncoerce,on);
        !           809:                                                        if (Ncoerce == 0) {
        !           810:                                                                Ncoerce = on;
        !           811:                                                                val++;
        !           812:                                                                std = 1;
        !           813:                                                        }       
        !           814:                                                }
        !           815:                                        }
        !           816:                                }
        !           817:                        }
        !           818: // error( 'd', "can_coerce: gl: %d", gl );
        !           819:                        if ( gl ) {
        !           820:                                on = gl->f;
        !           821:                                gl = gl->l;
        !           822:                                goto overlist; // must walk list of overloaded instances
        !           823:                        }
        !           824:                }
        !           825:        }
        !           826: //error('d',"val %d",val);
        !           827:        if (val) return val;
        !           828:        if (c1 && Pclass(c1->tp)->has_itor()) return 0;
        !           829: //error('d',"%t->check(%t) -> %d",t1,t2,t1->check(t2,COERCE));
        !           830:        if (t1->check(t2,COERCE)) return 0;
        !           831:        return 1;
        !           832: }
        !           833: 
        !           834: int gen_coerce(Pname n, Pexpr arg)
        !           835: /*
        !           836:        look to see if the argument list "arg" can be coerced into a call of "n"
        !           837:        1: it can
        !           838:        0: it cannot or it can be done in more than one way
        !           839: */
        !           840: {
        !           841:        Pfct f = (Pfct) n->tp;
        !           842:        register Pexpr e;
        !           843:        register Pname nn;
        !           844: 
        !           845: //error('d',"gen_coerce(%n,%d) %t",n,arg,n->tp);
        !           846:        for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
        !           847:                if (nn == 0) return f->nargs_known==ELLIPSIS;
        !           848:                Pexpr a = e->e1;
        !           849:                Ptype at = a->tp;
        !           850:                int i = can_coerce(nn->tp,at);
        !           851:                if (i != 1) return 0;
        !           852:        }
        !           853:        if (nn && nn->n_initializer==0) return 0;
        !           854:        return 1;
        !           855: }
        !           856: 
        !           857: 
        !           858: Pname Nover;
        !           859: // int Nover_coerce;
        !           860: 
        !           861: int over_call(Pname n, Pexpr arg)
        !           862: /*     
        !           863:        return 4 if n(arg) can be performed without coercion of arg
        !           864:        return 3 if n(arg) can be performed only with promotion coercion of arg
        !           865:        return 2 if n(arg) can be performed only with standard coercion of arg
        !           866:        return 1 if n(arg) can be performed only with user defined coercion of arg
        !           867:        return 0 if n(arg) is an error
        !           868:        Nover is the function found, if any
        !           869:        Nstd is the number of standard coercions used
        !           870: */
        !           871: {      
        !           872:        register Plist gl;
        !           873:        Pgen g = Pgen(n->tp);
        !           874:        if (arg && arg->base!= ELIST) error('i',"ALX");
        !           875: 
        !           876: //error('d',"over_call(%n) %k",n,n->tp->base);
        !           877:        extern suppress_error;
        !           878:        suppress_error = 1;
        !           879: //     Nover_coerce = 0;
        !           880:        Nstd = 0;
        !           881:        switch (g->base) {
        !           882:        default:        error('i',"over_call(%t)\n",g);
        !           883:        case OVERLOAD:  break;
        !           884:        case FCT:
        !           885:                Nover = n;
        !           886:                Ninit = 0;
        !           887:                if (exact_match(n,arg)) {suppress_error = 0; return 4;}
        !           888:                if (prom_match(n,arg)) {suppress_error = 0; return 3;}
        !           889:                if (std_match(n,arg) && Ninit==0) {suppress_error = 0; return 2;}
        !           890:                Nstd = 0;
        !           891:                suppress_error = 0;
        !           892:                return gen_coerce(n,arg);
        !           893:        }
        !           894: 
        !           895:        Pname exact = 0;
        !           896:        int no_exact = 0;
        !           897:        int ret = 0;
        !           898:        Pname nret;
        !           899:        for (gl=g->fct_list; gl; gl=gl->l) {            /* look for match */
        !           900:                Nover = gl->f;
        !           901:                Ninit = 0;
        !           902:                Nstd = 0;
        !           903:                if (exact_match(Nover,arg)) {suppress_error = 0; return 4;}     // no coercion
        !           904:        //      if (prom_match(Nover,arg)) return 3;    // only promotion
        !           905:        //      if (std_match(Nover,arg) && Ninit==0) return 2; // only built-in conversion
        !           906:                if (ret<3 && prom_match(Nover,arg)) {
        !           907:                        nret = Nover;
        !           908:                        ret = 3;
        !           909:                }
        !           910:                if (ret<2 && std_match(Nover,arg) && Ninit==0) {
        !           911:                        nret = Nover;
        !           912:                        ret = 2;
        !           913:                }
        !           914:        }
        !           915: 
        !           916: suppress_error = 0;
        !           917:        if (ret) {
        !           918:                Nover = nret;
        !           919:                return ret;
        !           920:        }
        !           921: 
        !           922:        Nover = 0;
        !           923:        for (gl=g->fct_list; gl; gl=gl->l) {            /* look for coercion */
        !           924:                Pname nn = gl->f;
        !           925:                if (gen_coerce(nn,arg)) {
        !           926:                        Nover = nn;
        !           927:                        return 1;
        !           928:                }
        !           929:        }
        !           930:        return 0;
        !           931: 
        !           932: }
        !           933: 
        !           934: Ptype expr::call_fct(Ptable tbl)
        !           935: /*
        !           936:        check "this" call:
        !           937:                 e1(e2)
        !           938:        e1->typ() and e2->typ() has been done
        !           939: */
        !           940: {
        !           941:        Pfct f;
        !           942:        Pname fn;
        !           943:        int x;
        !           944:        int k;
        !           945:        Pname nn;
        !           946:        Pexpr e;
        !           947:        Ptype t;
        !           948:        Pexpr arg = e2;
        !           949:        Ptype t1 = e1?e1->tp:0;
        !           950:        int argno;
        !           951:        Pexpr etail = 0;
        !           952:        bit no_change = 0;
        !           953:        Pname no_virt = 0;      // set if explicit qualifier was used: c::f()
        !           954:        Pname chk = 0;          // set if visibility check is needed
        !           955:                                // that is if function name might have been
        !           956:                                // found without use of find_name()
        !           957:        int const_obj = 0;
        !           958: 
        !           959:        if (t1 == any_type) return any_type;
        !           960: 
        !           961:        switch (base) {
        !           962:        case CALL:
        !           963:        case G_CALL:    break;
        !           964:        default:        error('i',"call_fct(%k)",base);
        !           965:        }
        !           966: 
        !           967: // error('d',"call %d %k %n arg %d",this,e1->base,e1->base==NAME?e1:0,arg);
        !           968:        if (t1 == 0) error('i',"call_fct(e1=%d,e1->tp=%t)",e1,t1);
        !           969:        if (arg && arg->base!=ELIST) error('i',"badAL%d%k",arg,arg->base);
        !           970: 
        !           971:        switch (e1->base) {
        !           972:        case NAME:
        !           973:                fn = Pname(e1);
        !           974: //error('d',"name %n %k",fn,fn->n_oper);
        !           975:                switch (fn->n_oper) {
        !           976:                case 0:
        !           977:                case CTOR:
        !           978:                case DTOR:
        !           979:                case TYPE:
        !           980:                case NEW:
        !           981:                case DELETE:
        !           982:                        break;
        !           983:                default:        // real operator: check for operator+(1,2);
        !           984:                        if (arg == 0) break;
        !           985:                        Pexpr a = arg->e1;      // first operand
        !           986: 
        !           987:                        if (Pfct(fn->tp)->memof // obj.operator(1) is OK
        !           988:                        || a->tp->is_cl_obj()
        !           989:                        || a->tp->is_ref()) break;
        !           990:                        a = arg->e2;
        !           991:                        if (a == 0)             // unary
        !           992:                                error("%k of basicT",fn->n_oper);
        !           993:                        else {                  // binary
        !           994:                                a = a->e1;      // second operand
        !           995:                                if (a->tp->is_cl_obj() || a->tp->is_ref()) break;
        !           996:                                error("%k of basicTs",fn->n_oper);
        !           997:                        }
        !           998:                        break;
        !           999:                }
        !          1000:                break;
        !          1001:        case REF:
        !          1002:        case DOT:
        !          1003:                no_virt = Pname(e1->n_initializer);
        !          1004:                e1->n_initializer = 0;
        !          1005:                if (e1 && e1->e1) {
        !          1006:                        Ptype t = e1->e1->tp;
        !          1007:                        Pptr tt = t->is_ptr_or_ref();
        !          1008:                        Ptype ft = tt ? tt->typ : t;
        !          1009:                        Pexpr ee = e1->e1;
        !          1010:                        const_obj = ft->tconst();
        !          1011:                        while (ee && (ee->base==DOT || ee->base==REF)) {
        !          1012:                                Pexpr m = ee->mem;
        !          1013:                                if ( ee->base==REF && m->tp &&  m->tp->is_ptr())
        !          1014:                                        break;
        !          1015:                                ee = ee->e1;
        !          1016:                        }
        !          1017:                        if (ee) {
        !          1018:                                Ptype ttt = ee->tp;
        !          1019:                                int tc;
        !          1020:                                switch (e1->base) {
        !          1021:                                case REF:
        !          1022:                                        Pptr p = ttt?ttt->is_ptr():0;
        !          1023:                                        if (p && p->typ->tconst())
        !          1024:                                                const_obj = 1;
        !          1025:                                        break;
        !          1026:                                case DOT:
        !          1027:                                        tc = ttt ? ttt->tconst() : 0;
        !          1028:                                        if(ttt && tc && (!strict_opt || tc!=2))
        !          1029:                                                const_obj = 1;
        !          1030:                                }
        !          1031:                        }
        !          1032:                }
        !          1033:        case MDOT:
        !          1034:        {       Pexpr n = e1->mem;
        !          1035:        lxlx:
        !          1036:                switch (n->base) {
        !          1037:                case MDOT:
        !          1038:                        // reverse mdot (see expr::print())
        !          1039:                        //      p->a.b()  => (&p->a)->b() => b(&p->a)
        !          1040:                        // or   p->a->b() => (p->a)->b()  => b(p->a)
        !          1041:                        // or   oo.a.b()  => (&oo.a)->b() => b(&oo.a)
        !          1042:                        // or   oo.a->b() => (oo.a)->b()  => b(oo.a)
        !          1043:                {       
        !          1044:                        Pexpr r = e1;
        !          1045:                        Pexpr p = r->e1;
        !          1046:                        for (Pexpr m = r->mem; m->base==MDOT; m = r->mem) {
        !          1047:                                p = new mdot(m->string2,p);
        !          1048:                                p->i1 = m->i1+2;
        !          1049:                                p->tp = p->mem->tp;
        !          1050:                                r->mem = m->mem;
        !          1051:                                r->e1 = p;
        !          1052:                        }
        !          1053:                }
        !          1054:                case REF:
        !          1055:                case DOT:
        !          1056:                        n = n->mem;
        !          1057:                        goto lxlx;
        !          1058:                case NAME:
        !          1059:                        break;
        !          1060:                default:
        !          1061:                        error('i',"ref %k",n->base);
        !          1062:                }
        !          1063:                fn = Pname(n);
        !          1064: //error('d',"mem %n",fn);
        !          1065:                break;
        !          1066:        }
        !          1067:        case MEMPTR:
        !          1068:        default:
        !          1069:                fn = 0;
        !          1070:        };
        !          1071: 
        !          1072: lll:
        !          1073: //error('d',"lll: %t %k",t1,t1->base);
        !          1074:        switch (t1->base) {
        !          1075:        case TYPE:
        !          1076:                t1 = Pbase(t1)->b_name->tp;
        !          1077:                goto lll;
        !          1078: 
        !          1079:        case PTR:       // pf() allowed as shorthand for (*pf)()
        !          1080:                switch (Pptr(t1)->typ->base) {
        !          1081:                case FCT:
        !          1082:                case OVERLOAD:
        !          1083:                        if (Pptr(t1)->memof) error("O missing in call throughP toMF");
        !          1084:                        t1 = Pptr(t1)->typ;
        !          1085:                        fn = 0;
        !          1086:                        goto lll;
        !          1087:                }
        !          1088: 
        !          1089:        default:
        !          1090:                if (fn)
        !          1091:                        error("call of%n;%n is a%t",fn,fn,e1->tp);
        !          1092:                else
        !          1093:                        error("call of%kE ofT%t",e1->base,e1->tp);
        !          1094: 
        !          1095:        case ANY:
        !          1096:                return any_type;
        !          1097:        
        !          1098:        case OVERLOAD:
        !          1099:        {       register Plist gl;
        !          1100:                Pgen g = Pgen(t1);
        !          1101:                Pname found = 0;
        !          1102:                Pname exact = 0;
        !          1103:                int no_exact = 0;
        !          1104:                int no_gen = 0;
        !          1105: 
        !          1106:                for (gl=g->fct_list; gl; gl=gl->l) {    // look for exact match
        !          1107:                        register Pname nn = gl->f;
        !          1108:                        if (exact_match(nn,arg)) {
        !          1109: //error('d',"found exact %n %t",nn,nn->tp);
        !          1110:                                if (found) {
        !          1111:                                        // check if one fct dominates the other
        !          1112:                                        Pname d = dominate(found,nn,arg,const_obj,0);
        !          1113:                                        if (d)
        !          1114:                                                nn = d;
        !          1115:                                        else
        !          1116:                                                error("two exact matches for%n:%t and%t",nn,nn->tp,found->tp);
        !          1117:                                }
        !          1118:                                found = nn;
        !          1119:                        }
        !          1120:                }
        !          1121: //error('d',"found exact2 %n",found);
        !          1122:                if (found) goto fnd;
        !          1123: 
        !          1124: Pname mvec[20];
        !          1125: 
        !          1126: /****************************************************************************
        !          1127:    the next 2 loops have been commented out to eliminate the rule that calls
        !          1128:    requiring only promotions and standard conversions are preferred over
        !          1129:    calls requiring user-defined conversions.
        !          1130: 
        !          1131:                for (gl=g->fct_list; gl; gl=gl->l) {    // look for exact match
        !          1132:                        register Pname nn = gl->f;
        !          1133: 
        !          1134:                        if (prom_match(nn,arg)) {
        !          1135:                                if (found) {
        !          1136:                                        // check if one fct dominates the other
        !          1137:                                        Pname d = dominate(found,nn,arg,const_obj,1);
        !          1138:                                        if (d)
        !          1139:                                                nn = d;
        !          1140:                                        else
        !          1141:                                                error("two exact matches (after integral promotions) for%n:%t and%t",nn,nn->tp,found->tp);
        !          1142:                                }
        !          1143:                                found = nn;
        !          1144:                        }
        !          1145:                }
        !          1146: //error('d',"found exact2 %n",found);
        !          1147:                if (found) goto fnd;
        !          1148: 
        !          1149:        //      for (gl=g->fct_list; gl; gl=gl->l) {    // look for exact match
        !          1150:        //              register Pname nn = gl->f;
        !          1151:        //
        !          1152:        //              if (exact_match(nn,arg) || prom_match(nn,arg)) {
        !          1153:        //                      found = nn;
        !          1154:        //                      goto fnd;
        !          1155:        //              }
        !          1156:        //      }
        !          1157: 
        !          1158:                for (gl=g->fct_list; gl; gl=gl->l) {    // look for match
        !          1159:                                                        // with standard conversion
        !          1160:                        register Pname nn = gl->f;
        !          1161:                        Ninit = 0;
        !          1162:                        Nstd = 0;
        !          1163:                        if (std_match(nn,arg)) {
        !          1164:                        //      if (Nstd == 0)  {
        !          1165:                        //              found = nn;
        !          1166:                        //              goto fnd;
        !          1167:                        //      }
        !          1168:                                if (exact) {
        !          1169:                                        // check if one fct dominates the other
        !          1170:                                        Pname d = dominate(exact,nn,arg,const_obj,2);
        !          1171:                                        if (d == 0) {
        !          1172:                                                mvec[no_exact++] = nn;
        !          1173:                                        //      no_exact++;
        !          1174:                                        //      error("two standard conversions possible for%n: %t and %t",fn,exact->tp,nn->tp);
        !          1175:                                        }
        !          1176:                                        else
        !          1177:                                                exact = d;
        !          1178:                                }
        !          1179:                                else
        !          1180:                                        exact = nn;
        !          1181:                        }
        !          1182:                        
        !          1183:                }
        !          1184: 
        !          1185: //error('d',"excact %n",exact);
        !          1186:                if (exact) {
        !          1187:                        if (no_exact) {
        !          1188:                                while (no_exact) {
        !          1189:                                        Pname d = dominate(exact,mvec[--no_exact],arg,const_obj,2);
        !          1190:                                        if (d)
        !          1191:                                                exact = d;
        !          1192:                                        else
        !          1193:                                                error("two standard conversions possible for%n: %t and %t",fn,exact->tp,mvec[no_exact]->tp);
        !          1194:                                }
        !          1195:                                
        !          1196:                        }
        !          1197: //error('d',"found exact3 %n",found);
        !          1198:                        found = exact;
        !          1199:                        goto fnd;
        !          1200:                }
        !          1201: 
        !          1202:     this is the end of the commented out section.
        !          1203: ************************************************************************/
        !          1204: 
        !          1205:                for (gl=g->fct_list; gl; gl=gl->l) {    /* look for coercion */
        !          1206:                        register Pname nn = gl->f;
        !          1207:                        if (prom_match(nn,arg) ||
        !          1208:                            std_match(nn,arg)  ||
        !          1209:                            gen_coerce(nn,arg)) {
        !          1210: //error('d',"user2 %n %t",nn,nn->tp);
        !          1211:                                if (found) {
        !          1212:                                        // check if one fct dominates the other
        !          1213:                                        Pname d = dominate(found,nn,arg,const_obj,3);
        !          1214: //error('d',"dom d %d",d);
        !          1215:                                        if (d == 0) d = user_dominate(found,nn,arg);
        !          1216:                                        if (d == 0) {
        !          1217:                                                mvec[no_gen++] = nn;
        !          1218:                                        }
        !          1219:                                        else
        !          1220:                                                found = d;
        !          1221:                                }
        !          1222:                                else
        !          1223:                                        found = nn;
        !          1224:                        }
        !          1225:                }
        !          1226:                if(found) {
        !          1227:                        while(no_gen) {
        !          1228:                                Pname d = dominate(found,mvec[--no_gen],arg,const_obj,3);
        !          1229:                                if(d==0) d = user_dominate(found,mvec[no_gen],arg);
        !          1230:                                if(d)
        !          1231:                                        found = d;
        !          1232:                                else {
        !          1233:                                        //error("ambiguousA for%n: %t and %t",fn,found->tp,mvec[no_gen]->tp);
        !          1234:                                        error("ambiguous call of%n: %t and %t",fn,found->tp,mvec[no_gen]->tp);
        !          1235:                                }
        !          1236:                        }
        !          1237:                }
        !          1238:        fnd:
        !          1239: //error('d',"fnd %t",found?found->tp:0);
        !          1240:                if (found) {
        !          1241:                        overFound = chk = fn = found;
        !          1242:                        f = Pfct(fn->tp);
        !          1243:                }
        !          1244:                else {
        !          1245:                        error("badAL for%n (no match against any %n)",fn,fn);
        !          1246:                        return any_type;
        !          1247:                }
        !          1248:                break;
        !          1249:        }
        !          1250:        case FCT:
        !          1251:                f = Pfct(t1);
        !          1252:                if (fn) {
        !          1253:                        switch (fn->n_oper) {
        !          1254:                        case CTOR:
        !          1255:                        case TYPE:
        !          1256:                                chk = fn;
        !          1257:                        }
        !          1258:                }
        !          1259:        }
        !          1260: 
        !          1261: //error('d',"chk %n",chk);
        !          1262:        if (chk) {
        !          1263:                Ptype t = 0;
        !          1264:                Pexpr ee = e1->e1;
        !          1265: 
        !          1266:                switch (e1->base) {
        !          1267:                case REF:       // ptr->chk()
        !          1268:                        if (ee == 0) {  // 0->x() fudge handling new x()
        !          1269:                                check_visibility(chk,no_virt,Pclass(chk->n_table->t_name->tp),tbl,cc->nof);
        !          1270:                                break;
        !          1271:                        };
        !          1272:                        t = ee->tp;
        !          1273:                        while(t->base==TYPE) t = Pbase(t)->b_name->tp;
        !          1274:                        t = Pptr(t)->typ;
        !          1275:                        break;
        !          1276:                case DOT:       // obj.chk()
        !          1277:                        t = ee->tp;
        !          1278:                }
        !          1279: 
        !          1280:                Pname cn = t?t->is_cl_obj():0;
        !          1281:                Pclass cl = cn?Pclass(cn->tp):0; // class of ``this'' for chk
        !          1282: 
        !          1283:                if (cl) {
        !          1284:                        if (chk->n_oper==CTOR
        !          1285:                                && chk->n_protect
        !          1286:                                && cc->nof
        !          1287:                                && cc->nof->n_oper==CTOR)
        !          1288:                                        // BUG: cannot handle protected base
        !          1289:                                        // class constructor
        !          1290:                                ;
        !          1291:                        else {
        !          1292:                                check_visibility(chk,no_virt,cl,tbl,cc->nof);
        !          1293:                        }
        !          1294:                }
        !          1295:        }
        !          1296: 
        !          1297:        if (fn && f->returns->is_cl_obj() && f->f_result==0) {
        !          1298:                // protect against class cn; cn f(); ... class cn { cn(cn&); ... };
        !          1299:                make_res(f);
        !          1300: //error('d',"returns %t",f->returns);
        !          1301:                f->returns->tsizeof();  // make sure it is declared
        !          1302:        }
        !          1303: 
        !          1304: //error('d',"fn %n %t printed %d",fn,fn?fn->tp:0,fn?fn->n_dcl_printed:0);
        !          1305:        if (fn && fn->n_dcl_printed==0) {
        !          1306:                if (f->f_inline==0 && f->f_imeasure) {
        !          1307:                        extern void uninline(Pname fn);
        !          1308:                        uninline(fn);
        !          1309:                }
        !          1310: 
        !          1311:                // ensure printout of class declaration:
        !          1312:                for (Pname nn=f->argtype; nn; nn=nn->n_list)
        !          1313:                        if (nn->tp->is_cl_obj()) (void) nn->tp->tsizeof();
        !          1314: 
        !          1315:                fn->dcl_print(0);
        !          1316:        }
        !          1317: 
        !          1318:        if (no_virt && f->f_static==0) {
        !          1319:                if (e1->base==REF || e1->base==DOT) e1->n_initializer = fn;
        !          1320:        }
        !          1321:        else
        !          1322:                fct_name = fn;
        !          1323: //error('d',"fn %n %t %d %d",fn,f,f->f_this,f->f_static);
        !          1324:        if (f->f_this) {        //SSS call of non-static memberfunction
        !          1325:                switch (e1->base) {
        !          1326:                case MEMPTR:
        !          1327:                case REF:
        !          1328:                case DOT:
        !          1329:                        break;
        !          1330:                default:
        !          1331:                        error("O orP missing for%n ofT %t",fct_name,f);
        !          1332:                }
        !          1333:        }
        !          1334:        else if (fn) {  //SSS call of static function
        !          1335:        sss:
        !          1336:                switch (e1->base) {
        !          1337:                case REF:
        !          1338:                case DOT:
        !          1339:                        e1 = e1->mem;
        !          1340:                        goto sss;
        !          1341:                }
        !          1342:        }
        !          1343: 
        !          1344:        if (fn) fn->use();      // a patch: ctors are sometimes not use()d
        !          1345: 
        !          1346:        if (f->f_const==0
        !          1347:        && (fn==0 || (fn->n_oper!=CTOR && fn->n_oper!=DTOR))) { //CCC
        !          1348:                Pexpr ee = e1->e1;
        !          1349:                 // while (ee && (ee->base==DOT || ee->base==REF)) ee = ee->e1;
        !          1350:                 while (ee && (ee->base==DOT || ee->base==REF)) {
        !          1351:                        Pexpr m = ee->mem;
        !          1352: // error('d', "m: %k tp %t", m?m->base:0, m?m->tp:0 ); 
        !          1353:                        if ( ee->base==REF && m->tp &&  m->tp->is_ptr())
        !          1354:                                break;
        !          1355:                        ee = ee->e1;
        !          1356:                }
        !          1357: // error('d', "ee: %k tp %k", ee?ee->base:0, ee?ee->tp->base:0);
        !          1358: 
        !          1359:                if (ee) {
        !          1360:                        Ptype tt = ee->tp;
        !          1361:                        switch (e1->base) {
        !          1362:                        case REF:
        !          1363:                        {       Pptr p = tt?tt->is_ptr():0;
        !          1364:                                if (p && p->typ->tconst())
        !          1365:                                        error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn);
        !          1366:                                // is really an error, but only warn to help transition
        !          1367:                                break;
        !          1368:                        }
        !          1369:                        case DOT:
        !          1370:                                int tc = tt ? tt->tconst() : 0;
        !          1371:                                if (tt && tc && (!strict_opt || tc!=2))
        !          1372:                                        error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn);
        !          1373:                                // is really an error, but only warn to help transition
        !          1374:                        }
        !          1375:                }
        !          1376:        }
        !          1377: 
        !          1378:        t = f->returns;
        !          1379:        x = f->nargs;
        !          1380:        k = f->nargs_known;
        !          1381: 
        !          1382:        e = arg;
        !          1383:        if (k == 0) goto rlab;
        !          1384: 
        !          1385:        for (nn=f->argtype, argno=1; e||nn; nn=nn->n_list, e=etail->e2, argno++) {
        !          1386:                Pexpr a;
        !          1387:                int save_base = 0;
        !          1388:                char* save_name = 0;
        !          1389: 
        !          1390:                if (e) {
        !          1391:                        a = e->e1;
        !          1392:                        etail = e;
        !          1393: 
        !          1394:                        if (nn) {       /* type check */
        !          1395:                                Ptype t1 = nn->tp;
        !          1396: //error('d',"argtp %t etp %t a %k",t1,a->tp,a->base);
        !          1397: 
        !          1398:                                while(t1->base == TYPE)
        !          1399:                                        t1 = Pbase(t1)->b_name->tp;
        !          1400: 
        !          1401:                                switch (t1->base) {
        !          1402:                                case RPTR:
        !          1403:                                {       Ptype pt = Pptr(t1)->typ;
        !          1404:                                        if (pt->base != FCT ||
        !          1405:                                                ( pt->base == FCT && 
        !          1406:                                                  pt->check(a->tp,0)))
        !          1407:                                                        a = ref_init(Pptr(nn->tp),a,tbl);
        !          1408:                                        goto cbcb;
        !          1409:                                }
        !          1410:                                case COBJ:
        !          1411:                                        if (a->base!=G_CM
        !          1412:                                        || nn->tp->check(a->tp,ASSIGN))
        !          1413:                                                a = class_init(0,t1,a,tbl);
        !          1414:                                        else
        !          1415:                                                a->e2=class_init(0,t1,a->e2,tbl);
        !          1416:                                        if (nn->n_xref) {
        !          1417:                                                // (temp.ctor(arg),&arg)
        !          1418:                                                a = a->address();
        !          1419:                                        }
        !          1420:                                        else {
        !          1421:                                                // defend against:
        !          1422:                                                //      int f(X); ... X(X&);
        !          1423:                                                Pname cln = Pbase(t1)->b_name;  
        !          1424:                                                if (cln && Pclass(cln->tp)->has_itor()) {
        !          1425:                                                        // mark X(X&) arguments
        !          1426:                                                        nn->n_xref = 1;
        !          1427:                                                        a = a->address();
        !          1428:                                                }
        !          1429:                                        }
        !          1430:        cbcb:
        !          1431: //error('d',"cbcb: a %d %k %t",a->base,a->base,a->tp);
        !          1432:                if (a->base==G_CM) {
        !          1433:                        if (a->e1->base==DEREF) a->e1 = a->e1->e2; // (*e1,e2) => (e1,e2)
        !          1434: //error('d',"      a %d %k",a->e1->base,a->e1->base);
        !          1435:                        if (a->e1->base==G_CALL
        !          1436:                        && Pname(a->e1->fct_name)
        !          1437:                        && Pname(a->e1->fct_name)->n_oper==CTOR
        !          1438:                        && (a->e2->base==G_ADDROF || a->e2->base==ADDROF)) {
        !          1439:                                a = a->e1;      // (ctor(&tmp),&tmp) => ctor(&tmp)
        !          1440: //error('d',"tmp %k %n",a->e2->base,a->e2->e2);
        !          1441:                                goto cccc;
        !          1442:                        }
        !          1443:                        else if (a->e2->base==G_ADDROF
        !          1444:                        && a->e2->e2->base==NAME)  {
        !          1445:                        cccc:
        !          1446: //error('d',"cccc: a %d %k %t",a->base,a->base,a->tp);
        !          1447:        if (t1->base==RPTR
        !          1448:        && Pptr(t1)->typ->tconst()==0) {        // temporary used
        !          1449:                if (warning_opt)
        !          1450:                        error('w',"temporary used for non-const%tA",nn->tp);
        !          1451:                else {
        !          1452:                        Ptype atp = a->tp;
        !          1453:                        if (atp==void_type
        !          1454:                        && a->base==G_CALL
        !          1455:                        && a->e1->tp->base==FCT)
        !          1456:                                atp = Pfct(a->e1->tp)->s_returns;
        !          1457: 
        !          1458:                        Ptype tt = t1->is_ref();
        !          1459: //error('d',"tt %t atp %t",tt,atp);
        !          1460:                        if (tt) {
        !          1461:                                if (Pptr(tt)->typ->tsizeof()!=atp->tsizeof()) { // sliced
        !          1462:                                        Ptype aat = atp->is_ptr_or_ref();
        !          1463:                                        if (aat==0
        !          1464:                                        || Pptr(tt)->typ->tsizeof()!=Pptr(aat)->typ->tsizeof())
        !          1465:                                                error('w',"temporary used for non-const%tA",nn->tp);
        !          1466:                                }
        !          1467:                        }
        !          1468:                        else if (t1->tsizeof()!=atp->tsizeof()) // sliced
        !          1469:                                error('w',"temporary used for non-const%tA",nn->tp);
        !          1470:                }
        !          1471:                
        !          1472:        //      if (warning_opt                         // blabber
        !          1473:        //      ||  t1->tsizeof()!=a->tp->tsizeof()))   // sliced
        !          1474:        //              error('w',"temporary used for non-const%tA",nn->tp);
        !          1475: 
        !          1476:        }
        !          1477:                        }
        !          1478:                }
        !          1479:                                        e->e1 = a;
        !          1480:                                        break;
        !          1481:                                case ANY:
        !          1482:                                        goto rlab;
        !          1483:                                case PTR:
        !          1484:                                {
        !          1485:                                        save_base = e->e1->base;
        !          1486:                                        if(a->tp->base==OVERLOAD)
        !          1487:                                                save_name = Pgen(a->tp)->fct_list->f->string;
        !          1488:                                        Pexpr te_a = a;
        !          1489:                                        e->e1 = a = ptr_init(Pptr(t1),a,tbl);
        !          1490:                                        no_change = (te_a == a);
        !          1491:                                //      if (x==a || x==a->e2) goto def; // needs checking
        !          1492:                                        if (Pchecked == 0) goto def;
        !          1493:                                        break;
        !          1494:                                }
        !          1495:                                //      e->e1 = a = ptr_init(Pptr(t1),a,tbl);
        !          1496:                                //      goto def;
        !          1497:                                case CHAR:
        !          1498:                                case SHORT:
        !          1499:                                case INT:
        !          1500:                                //      if (a->base==ICON && a->tp==long_type)
        !          1501:                                //              error('w',"long constantA for%n,%kX",fn,t1->base);
        !          1502:                                {       Ptype t = a->tp;
        !          1503:                                        while(t->base == TYPE)
        !          1504:                                                t = Pbase(t)->b_name->tp;
        !          1505: 
        !          1506:                                        switch (t->base) {
        !          1507:                                        case LONG:
        !          1508:                                        case FLOAT:
        !          1509:                                        case DOUBLE:
        !          1510:                                        case LDOUBLE:
        !          1511:                                                error('w',"A%d: %t passed as %t",argno,a->tp,t1);
        !          1512:                                        }
        !          1513:                                }
        !          1514:                                        // no break
        !          1515:                                case LONG:
        !          1516:                                        if (Pbase(t1)->b_unsigned
        !          1517:                                        && a->base==UMINUS
        !          1518:                                        && a->e2->base==ICON)
        !          1519:                                                error('w',"negativeA for%n, unsignedX",fn);
        !          1520:                                default:
        !          1521:                                def:
        !          1522:                                {       Pexpr x = try_to_coerce(t1,a,"argument",tbl);
        !          1523: //error('d',"x %d t1 %t nn %t a1 %t",x,t1,nn->tp,a->tp);
        !          1524:                                        if (x) {
        !          1525:                                                if (Pchecked == 0 && no_change) { 
        !          1526:                                                        Pexpr te_x = ptr_init(Pptr(t1), x, tbl);
        !          1527: 
        !          1528:                                                        if ( te_x != x ) e->e1 = a = te_x; else e->e1=x;
        !          1529:                                                }
        !          1530:                                                else
        !          1531:                                                        e->e1 = x;
        !          1532:                                        }
        !          1533:                                        else if (nn->tp->check(a->tp,ARG)) {
        !          1534:                                                error("badA %dT for%n:%t (%tX)",argno,fn,a->tp,nn->tp);
        !          1535:                                                return any_type;
        !          1536:                                        }
        !          1537:                                }
        !          1538:                                }
        !          1539: 
        !          1540:                                 Pexpr tt = e->e1;
        !          1541:                                 while ( tt->base == CAST )
        !          1542:                                         tt = tt->e1;
        !          1543:                                 if ( tt->base == ILIST )
        !          1544:                                         e->e1 = tt;
        !          1545: 
        !          1546:                                 if (e->e1->base == ILIST) {
        !          1547:                                         // memptr constant
        !          1548:                                         // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
        !          1549:                                        if(save_base == REF) {
        !          1550:                                                Pptr m = Pptr(a->tp);
        !          1551:                                                error(strict_opt?0:'w',
        !          1552:                                                "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)",
        !          1553:                                                m->memof->string,
        !          1554:                                                m->memof->string,
        !          1555:                                                save_name
        !          1556:                                                );
        !          1557:                                        }
        !          1558:                                         Pname temp = make_tmp('A',mptr_type,tbl);
        !          1559:                                         e->e1 = mptr_assign(temp,e->e1);
        !          1560:                                         e->e1 = a = new expr(G_CM,e->e1,temp);
        !          1561:                                         a->tp = temp->tp;
        !          1562:                                 }
        !          1563: 
        !          1564:                        }
        !          1565:                        else {
        !          1566:                                if (k != ELLIPSIS) {
        !          1567:                                        error("unexpected %dA for%n",argno,fn);
        !          1568:                                        return any_type;
        !          1569:                                }
        !          1570:                                Pexpr te=e;
        !          1571:                                while(e) {
        !          1572:                                        if (e->e1->base == ILIST) {
        !          1573:                                                // memptr constant
        !          1574:                                                // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
        !          1575:                                                Pname temp = make_tmp('A',mptr_type,tbl);
        !          1576:                                                e->e1 = mptr_assign(temp,e->e1);
        !          1577:                                                e->e1 = a = new expr(G_CM,e->e1,temp);
        !          1578:                                                a->tp = temp->tp;
        !          1579:                                        }
        !          1580:                                        e = e->e2;
        !          1581:                                }
        !          1582:                                e = te;
        !          1583:                                goto rlab;
        !          1584:                        }
        !          1585:                }
        !          1586:                else {  /* default argument? */
        !          1587:                        a = nn->n_initializer;
        !          1588:                        if (a == 0) {
        !          1589:                                error("A %d ofT%tX for%n",argno,nn->tp,fn);
        !          1590:                                return any_type;
        !          1591:                        }
        !          1592:                                 if (a->base == ILIST) {
        !          1593:                                         // memptr constant
        !          1594:                                         // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
        !          1595:                                         Pname temp = make_tmp('A',mptr_type,tbl);
        !          1596:                                         a = mptr_assign(temp,a);
        !          1597:                                         a = new expr(G_CM,a,temp);
        !          1598:                                         a->tp = temp->tp;
        !          1599:                                 }
        !          1600:                        a->permanent = 2;       // ought not be necessary, but it is
        !          1601:                        e = new expr(ELIST,a,0);
        !          1602:                        if (etail)
        !          1603:                                etail->e2 = e;
        !          1604:                        else
        !          1605:                                e2 = e;
        !          1606:                        etail = e;
        !          1607:                }
        !          1608:        }
        !          1609: 
        !          1610: rlab:
        !          1611: //error('d',"rlab fct_name %n %t",fct_name,fct_name?fct_name->tp:0);
        !          1612:        for (; e; e = e->e2) {  // unchecked arguments
        !          1613:                Pexpr a = e->e1;
        !          1614:                Pname cn;
        !          1615: 
        !          1616:                if (a->base==NAME && a->tp->base==FCT) {
        !          1617:                        // function name that escaped the type system:
        !          1618:                        // update use count
        !          1619:                        a->lval(ADDROF);
        !          1620:                }
        !          1621:                else if (warning_opt && (cn = a->tp->is_cl_obj())) {
        !          1622:                        Pclass cl = Pclass(cn->tp);
        !          1623:                        if (cl->has_ctor() || cl->memtbl->look("__as",0))//cl->has_oper(ASSIGN)
        !          1624:                        {
        !          1625:                                if (fct_name)
        !          1626:                                error('w',"O ofC%t withK or = copied asA to%n (%t)",cl,fct_name,fct_name->tp);
        !          1627:                                else
        !          1628:                                error('w',"O ofC%t withK or = copied asA to `...'",cl);
        !          1629:                        }
        !          1630:                }
        !          1631:                else if (a->tp->is_ref())
        !          1632:                        e->e1 = a->contents();
        !          1633:        }
        !          1634: 
        !          1635:        if (f->f_result) {              // f(args) => (f(&temp,args),temp)
        !          1636:                Pname tn = make_tmp('R',f->returns,tbl);
        !          1637:                e2 = new expr(ELIST,tn->address(),e2);
        !          1638: // error('d',"result %n refd: %d",fn, refd);
        !          1639:                Pexpr ee = new expr(0,0,0);
        !          1640:                *ee = *this;
        !          1641:                base = G_CM;            // (f(&temp,args),temp)
        !          1642:                e1 = ee;
        !          1643:                if (refd == 2)
        !          1644:                        e2 = tn->address();
        !          1645:                else e2 = tn;
        !          1646:                tp = tn->tp;
        !          1647:        }
        !          1648: 
        !          1649:        return t;
        !          1650: }
        !          1651: 
        !          1652: int cm_const_save; 
        !          1653: 
        !          1654: Pexpr ref_init(Pptr p, Pexpr init, Ptable tbl)
        !          1655: /*
        !          1656:        initialize the "p" with the "init"
        !          1657:        remember to call ptr_init to ensure that pointers to second bases
        !          1658:        are handled correctly.
        !          1659: */
        !          1660: {
        !          1661:        register Ptype it = init->tp;
        !          1662:        Pptr px = p;
        !          1663:        while (px->base == TYPE) px = Pptr(Pbase(px)->b_name->tp);
        !          1664:        Ptype p1 = px->typ;
        !          1665:        Pname c1 = p1->is_cl_obj();
        !          1666: // error('d',"ref_init: p %t, p1 %t, px %t, init->tp %t",p,p1,px,it);
        !          1667: // error('d', "ref_init: nof: %n f_const: %d", cc?cc->nof:0, cc?(cc->nof?Pfct(cc->nof->tp)->f_const:0):0);
        !          1668: 
        !          1669:        if (init->base == ILIST) error("IrL as RIr");
        !          1670: 
        !          1671:        if (init->base==NAME
        !          1672:        && Pname(init)->n_scope==ARG
        !          1673:        && init->tp->base==FLOAT)
        !          1674:                error('w',"initializing a float& with floatA is non-portable");
        !          1675: 
        !          1676:        while(it->base == TYPE)
        !          1677:                it = Pbase(it)->b_name->tp; 
        !          1678: 
        !          1679:        switch (it->base) {
        !          1680:        default:
        !          1681:                {       Ptype tt = it->addrof();
        !          1682:                        px->base = PTR; // allow &x for y& when y : public x
        !          1683:                                        // but not &char for int&
        !          1684:                        int x = px->check(tt,COERCE);
        !          1685: 
        !          1686:                        if (x == 0) {   //CCC type is fine check for constness:
        !          1687:                                if (init->tp->tconst()
        !          1688:                                && vec_const==0
        !          1689:                                && fct_const==0) {
        !          1690:                                        // not ``it''
        !          1691:                                        if (init->base == ELIST) init = init->e1;
        !          1692:                                        if (px->typ->tconst() == 0) error("R to constO");
        !          1693:                                        px->base = RPTR;
        !          1694:                                        // if we have a const lvalue we can still pass its address
        !          1695:                                        ignore_const++;
        !          1696:                                        if (init->lval(0)) {
        !          1697:                                                init->lval(ADDROF); // force output
        !          1698:                                                ignore_const--;
        !          1699: //error('d',"in1 %t",init->tp);
        !          1700:                                                return ptr_init(px,init->address(),tbl);//return init->address();
        !          1701:                                        }
        !          1702:                                        ignore_const--;
        !          1703:                                        goto xxx;
        !          1704:                                }
        !          1705:                                px->base = RPTR;
        !          1706:                                 if (init->lval(0)) {   // can pass the address                                                 // no temporary needed 
        !          1707:                                        init->lval(ADDROF); // force output
        !          1708: //error('d',"px %t init %t init %t",px,init->tp,init->tp);
        !          1709:                                        return ptr_init(px,init->address(),tbl);
        !          1710:                                }
        !          1711:                                goto xxx;
        !          1712:                        }
        !          1713: 
        !          1714:                        px->base = RPTR;
        !          1715:                }
        !          1716:        }
        !          1717: 
        !          1718: //error('d',"c1 %n",c1);
        !          1719:        if (c1) {       // assigning to a const X & is fine
        !          1720:                ref_cast++;
        !          1721:                Pexpr x = try_to_coerce(p,init,"reference initialization",tbl);
        !          1722:                ref_cast--;
        !          1723:                if (x) {
        !          1724:                        init = x;
        !          1725:                        goto xxx;
        !          1726:                }
        !          1727:                while (p1->base==TYPE) p1 = Pbase(p1)->b_name->tp;
        !          1728:                int bc = Pbase(p1)->b_const;
        !          1729:                Pbase(p1)->b_const = 0;
        !          1730: //             refd = 1;       
        !          1731:                switch ( init->base ) {
        !          1732:                        case STRING: case ZERO: case CCON:
        !          1733:                        case ICON: case FCON: case IVAL:
        !          1734:                        case NAME:
        !          1735:                                refd = 1; 
        !          1736:                                break;
        !          1737:                        default:
        !          1738:                                refd = (init->e1 && init->e1->base == NAME && 
        !          1739:                                        init->e1->tp->base != RPTR &&
        !          1740:                                        Pname(init->e1)->n_xref == 0) ? 2: 1;
        !          1741:                                break;
        !          1742:                }
        !          1743: // error('d', "***** refd: %d", refd );
        !          1744:                Pexpr a = class_init(0,p1,init,tbl);
        !          1745:                Pbase(p1)->b_const = bc;
        !          1746:                refd = 0;
        !          1747:                if (a==init && init->tp!=any_type) goto xxx;
        !          1748: // error('d',"ri a %d %k",a->base,a->base);
        !          1749:                switch (a->base) {
        !          1750:                case G_CALL:
        !          1751:        //      case CM:
        !          1752:        //      case G_CM:
        !          1753:                        init = a;
        !          1754:                        goto xxx;
        !          1755:                }
        !          1756:                a = a->address();
        !          1757:                a =  ptr_init(px,a,tbl);
        !          1758:                return a;
        !          1759: //             return ptr_init(px,a->address(),tbl);//a->address();
        !          1760:        }
        !          1761: 
        !          1762: //error('d',"p1 %t it %t",p1,it);
        !          1763:        if (p1->check(it,0)) {
        !          1764: 
        !          1765:                if (p1->check(it,ASSIGN) == 0) {
        !          1766:                //      if (p1->is_ptr())  // check for base* = derived*
        !          1767:                //              goto xxx;
        !          1768: 
        !          1769:                        // things like ``double& rr = 1;'' temporary needed
        !          1770:                        // warn in case of ``slightly wrong lvalue'', e.g.
        !          1771:                        //      int i; double& r = i;
        !          1772:                        if (init->lval(0) && p1->tconst()==0)
        !          1773:                                error('w',"temporary used toIR; no changes will be propagated to actualA");
        !          1774:                        goto def;
        !          1775:                }
        !          1776: 
        !          1777:                Pexpr x = try_to_coerce(p1,init,"reference",tbl);       // x==init
        !          1778:                if (x==0) x = try_to_coerce(px,init,"reference",tbl);   // x&=init
        !          1779:                if (x) {
        !          1780:                        init = x;
        !          1781:                        goto def;
        !          1782:                }
        !          1783: 
        !          1784:                error("badIrT:%t (%tX)",it,p);
        !          1785:                if (init->base != NAME) init->tp = any_type;
        !          1786:                return init;
        !          1787:        }
        !          1788:        
        !          1789: xxx:   /*
        !          1790:                here comes the test of a ``fundamental theorem'':
        !          1791:                a structure valued expression is
        !          1792:                        (1) an lvalue of type T (possibly const)
        !          1793:                or      (2) the result of a function (a _result if X(X&) is defined)
        !          1794:                or      (3) a * or [] or ? or , expression
        !          1795:        */
        !          1796: //error('d',"xxx %k %d %t",init->base,init->base,init->tp);
        !          1797: 
        !          1798:        switch (init->base) {
        !          1799:        case NAME:
        !          1800:        case DEREF:
        !          1801:        case REF:
        !          1802:        case DOT:                       // init => &init
        !          1803:                if (it->tconst() && vec_const==0 && fct_const==0) goto def;
        !          1804:                if ( cc && cc->nof && 
        !          1805:                        Pfct(cc->nof->tp)->f_const ) 
        !          1806:                                cm_const_save = Pbase(p->typ)->b_const;
        !          1807:                init->lval(ADDROF);
        !          1808:                cm_const_save = 0;
        !          1809: 
        !          1810:                if (vec_const) return init;
        !          1811:                if (fct_const && p1->is_ptr()) goto def;        // fptr& = fct
        !          1812:                // no break
        !          1813:        case CM:
        !          1814:        case G_CM:                      // & (f(&temp), temp)
        !          1815:                return ptr_init(px,init->address(),tbl);//init->address();
        !          1816:        default:
        !          1817:        def:
        !          1818:        {
        !          1819: // error('d',"def: init->tp %t p1 %t ",init->tp,p1);   
        !          1820: // error('d',"p1: %t const_ptr: %d", p1, const_ptr);
        !          1821:                if (const_ptr == 0) {
        !          1822:                        if (tbl == gtbl || strict_opt) 
        !          1823:                                error("Ir for%snon-constR not an lvalue", strict_opt?"":" global ");
        !          1824:                        else
        !          1825:                        if (warning_opt) 
        !          1826:                                error('w', "Ir for non-constR not an lvalue (anachronism)");
        !          1827:                }
        !          1828: 
        !          1829:                 Pname tcl = p1->is_cl_obj ();
        !          1830:                 if(tcl && Pclass(tcl->tp)->c_abstract)
        !          1831:                        error("a temporary is needed for a parameter, but the argument type is abstract class %t.", tcl->tp);
        !          1832: 
        !          1833:                Pname n = make_tmp('I',p1,tbl);
        !          1834:                Pexpr a;
        !          1835:                Pname ic = init->tp->is_cl_obj();
        !          1836: 
        !          1837:                if (p1->tconst()==0
        !          1838:                && (init->tp->tconst() && vec_const==0 && fct_const==0)
        !          1839:                && p1->check(it,ASSIGN)==0)
        !          1840:                        error('w',"constIr: temporary used toI reference");
        !          1841: 
        !          1842:                switch (p1->base) {
        !          1843:                case INT:
        !          1844:                case CHAR:
        !          1845:                case SHORT:
        !          1846:                        switch (it->base) {
        !          1847:                        case LONG:
        !          1848:                        case FLOAT:
        !          1849:                        case DOUBLE:
        !          1850:                        case LDOUBLE:
        !          1851:                                error('w',"%t assigned to %t inRIr",it,p1);
        !          1852:                        }
        !          1853:                }
        !          1854: 
        !          1855:                if (ic!=c1 && Pclass(ic->tp) != Pclass(c1->tp)) {
        !          1856:                        // derived class1 => must cast: ``it Ix; (Ix=init,(p)&Ix);''
        !          1857:                        n->tp = init->tp;
        !          1858:                        a = ptr_init(px,n->address(),tbl);//n->address();
        !          1859:                        PERM(p);
        !          1860:                        a = new texpr(CAST,p,a);
        !          1861:                        a->tp = p;
        !          1862:                }
        !          1863:                else
        !          1864:                        a = n->address();
        !          1865: 
        !          1866:                refd = 1;
        !          1867:                Pexpr as = init_tmp(n,init,tbl);
        !          1868:                refd = 0;
        !          1869:                a = new expr(G_CM,as,a);
        !          1870:                a->tp = a->e2->tp;
        !          1871:                return a;
        !          1872:        }
        !          1873:        }
        !          1874: }
        !          1875: 
        !          1876: Pexpr class_init(Pexpr nn, Ptype tt, Pexpr init, Ptable tbl)
        !          1877: /*
        !          1878:        initialize "nn" of type "tt" with "init"
        !          1879:        if nn==0 make a temporary,
        !          1880:        nn may not be a name
        !          1881: */
        !          1882: {      
        !          1883:        if (init == dummy) return 0;
        !          1884: //error('d',"class_init %t with %t init %k refd %d",tt,init->tp,init->base,refd);
        !          1885:        Pname c1 = tt->is_cl_obj();
        !          1886: 
        !          1887:         if (init == 0) {
        !          1888:                 error("emptyIr");
        !          1889:                 return dummy;
        !          1890:         }
        !          1891: 
        !          1892:        if (c1) {
        !          1893:                Pclass cl = Pclass(c1->tp);
        !          1894:                Pname c2 = init->tp->is_cl_obj();
        !          1895: 
        !          1896:                if (c1!=c2 || (refd==0 && cl->has_itor())) {
        !          1897:                        /*      really ought to make a temp if refd,
        !          1898:                                but ref_init can do that
        !          1899:                        */
        !          1900:                        int i = can_coerce(tt,init->tp);
        !          1901: //error('d',"i %d nn %n",i,nn);
        !          1902:                        switch (i) {
        !          1903:                        default:
        !          1904:                                error("%d ways of making a%n from a%t",i,c1,init->tp);
        !          1905:                                init->tp = any_type;
        !          1906:                                return init;
        !          1907:                        case 0:
        !          1908:                                if (c2 && Pclass(c2->tp)->has_base(cl)) {
        !          1909:                                        init = init->address();
        !          1910:                                        Pexpr x = cast_cptr(cl,init,tbl,0);
        !          1911: 
        !          1912:                                        if (x == init) {
        !          1913:                                                Ptype pt = tt->addrof();
        !          1914:                                                PERM(pt);
        !          1915:                                                x = new cast(pt,init);
        !          1916:                                        }
        !          1917: 
        !          1918:                                        return x->contents();
        !          1919:                                }
        !          1920:                                error("cannot make a%n from a%t",c1,init->tp);
        !          1921:                                init->tp = any_type;
        !          1922:                                return init;
        !          1923:                        case 1:
        !          1924: //error('d',"ncoerce %n %k %d",Ncoerce,init->base,init->base);
        !          1925:                                if (Ncoerce == 0) {
        !          1926:                                        Pexpr a = new expr(ELIST,init,0);
        !          1927:                                        a = new texpr(VALUE,tt,a);
        !          1928:                                        a->e2 = nn;
        !          1929:                                //      return a->typ(tbl);
        !          1930:                                        a = a->typ(tbl);
        !          1931: //error('d',"ci a %k %d %t",a->base,a->base,a->tp);
        !          1932:                                        return a;
        !          1933:                                }
        !          1934: 
        !          1935:                                switch (init->base) {
        !          1936:                                case CM:
        !          1937:                                case G_CM:      //ddd
        !          1938:                                case NAME:      /* init.coerce() */
        !          1939:        /* *ref */              case DEREF:
        !          1940:                                {       Pref r = new ref(DOT,init,Ncoerce);
        !          1941:                                        Pexpr rr = r->typ(tbl);
        !          1942:                                        init = new expr(G_CALL,rr,0);
        !          1943:                                        init->fct_name = Ncoerce;
        !          1944:                                        break;
        !          1945:                                }
        !          1946:                                default:        // (temp=init,temp.coerce())
        !          1947:                                {       Pname tmp = make_tmp('U',init->tp,tbl); 
        !          1948:                                        int x = refd;   
        !          1949:                                        refd = 0;       // ??
        !          1950:                                        Pexpr ass = init_tmp(tmp,init,tbl);
        !          1951:                                        refd = x;
        !          1952:                                        Pref r = new ref(DOT,tmp,Ncoerce);
        !          1953:                                        Pexpr rr = r->typ(tbl);
        !          1954:                                        Pexpr c = new expr(G_CALL,rr,0);
        !          1955:                                        c->fct_name = Ncoerce;
        !          1956:                                        c = c->typ(tbl);
        !          1957:                                        init = new expr(CM,ass,c);
        !          1958:                                        init->tp = c->tp;
        !          1959:                                        if (refd) {     // &f() => (t=f(), &t)
        !          1960:                                                Pname tmp2 = make_tmp('L',c->tp,tbl); 
        !          1961:                                                ass = init_tmp(tmp2,init,tbl);
        !          1962:                                                init = new expr(G_CM,ass,tmp2);
        !          1963:                                        }
        !          1964:                                }
        !          1965:                                }
        !          1966: //error('d',"nn %n",nn);
        !          1967:                                if (nn) {
        !          1968:                                        Pexpr a = new expr(ELIST,init,0);
        !          1969:                                        a = new texpr(VALUE,tt,a);
        !          1970:                                        a->e2 = nn;
        !          1971:                                        return a->typ(tbl);
        !          1972:                                }
        !          1973:                        }
        !          1974: //error('d',"c1 %n c2 %n",c1,c2);
        !          1975:                        return init->typ(tbl);
        !          1976:                }
        !          1977:                return init;
        !          1978:        }
        !          1979: //error('d',"ci check tt %t init->tp %t",tt,init->tp);
        !          1980:        if (tt->check(init->tp,ASSIGN) && refd==0) {
        !          1981:                error("badIrT:%t (%tX)",init->tp,tt);
        !          1982:                init->tp = any_type;
        !          1983:        }
        !          1984: 
        !          1985:        return init;
        !          1986: }
        !          1987: 
        !          1988: extern int bound;      // fudge for bound pointers to functions
        !          1989: 
        !          1990: Pexpr expr::docast(Ptable tbl)
        !          1991: {      
        !          1992:        // check cast against value, INCOMPLETE
        !          1993: 
        !          1994: //error('d',"docast %d %t %k",this,tp2,e1->base);
        !          1995:        if (e1 == dummy) {
        !          1996:                error("E missing for cast");
        !          1997:                tp = any_type;
        !          1998:                return this;
        !          1999:        }
        !          2000: 
        !          2001:        int pmf = 0;
        !          2002:        int ptom_cast = 0;
        !          2003:        Pexpr ee = e1;
        !          2004: 
        !          2005: //error('d',"ee %k %d",ee->base,ee->base);
        !          2006:        switch (ee->base) {
        !          2007:        case ADDROF:
        !          2008:                ee = ee->e2;
        !          2009:                switch (ee->base) {
        !          2010:                case NAME:      goto nm;
        !          2011:                case REF:       goto rf;
        !          2012:                }
        !          2013:                break;
        !          2014: 
        !          2015:        case NAME:
        !          2016:        nm:
        !          2017:                if (Pname(ee)->n_qualifier) pmf = 1;
        !          2018:                break;
        !          2019:                
        !          2020:        case REF:
        !          2021:        rf:
        !          2022:                if (ee->e1->base == THIS) bound = 1;
        !          2023:                break;
        !          2024:        }
        !          2025: 
        !          2026:        e1 = e1->typ(tbl);
        !          2027: 
        !          2028:        int b = bound;  // distinguish between explicit and implicit THIS
        !          2029:        bound = 0;
        !          2030:        pmf = pmf && e1->base==CAST;
        !          2031: 
        !          2032:        Ptype etp = e1->tp;
        !          2033:        Ptype tt = tp2;
        !          2034:        Ptype t = tt;
        !          2035:        tt->dcl(tbl);
        !          2036: 
        !          2037:        while (etp->base == TYPE) etp = Pbase(etp)->b_name->tp;
        !          2038:        while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp;
        !          2039:        
        !          2040: //error('d',"e1 %k etp %t tt %t",e1->base,etp,tt);
        !          2041: 
        !          2042:        switch (etp->base) {
        !          2043:        case PTR:
        !          2044:        case RPTR:
        !          2045:                if (Pptr(etp)->typ->base == OVERLOAD) goto over;
        !          2046: 
        !          2047:                if (warning_opt && i2==0 && Pptr(etp)->typ->tconst()) {
        !          2048:                        switch (tt->base) {
        !          2049:                        case FCT:
        !          2050:                                break;
        !          2051:                        case PTR:
        !          2052:                        case RPTR:
        !          2053:                                if (Pptr(tt)->typ->tconst()) break;
        !          2054:                        default:
        !          2055:                                // casting away const
        !          2056:                                // should be an error
        !          2057:                                // but ANSI says OK so I chicken out
        !          2058:                                // to be able to compile strtok(), etc.
        !          2059:                                error('w',"const cast away:%t->%t",e1->tp,tp2);
        !          2060:                        }
        !          2061:                }
        !          2062:                else
        !          2063:                        i2 = 0; // to allow cfront to escape its own checking
        !          2064:                break;
        !          2065:        case COBJ:
        !          2066:        {       ref_cast = 1;
        !          2067:                Pexpr x = try_to_coerce(tt,e1,"cast",tbl);
        !          2068:                ref_cast = 0;
        !          2069: //error('d',"x %k %t tt %d %t",x?x->base:0,x?x->tp:0,tt,tt);
        !          2070:                if (x) {
        !          2071:                        if (x!=e1 && x->base==DEREF && tt->is_ref()) x = x->e1;
        !          2072:                        if (tt==x->tp || tt->check(x->tp,0)==0 || const_problem)
        !          2073:                                return x;
        !          2074:                        else
        !          2075:                                return new cast(tt,x);
        !          2076:                }
        !          2077:        //      else if (e1->base==DEREF && tt->is_ref()) return e1;
        !          2078:                break;
        !          2079:        }
        !          2080:        case VOID:
        !          2081:                if (tt->base == VOID) {
        !          2082:                        tp = t;
        !          2083:                        return this;
        !          2084:                }
        !          2085:                error("cast of void value");
        !          2086:                // no break;
        !          2087:        case ANY:
        !          2088:        any:
        !          2089:                tp = any_type;
        !          2090:                return this;
        !          2091:        case FCT:
        !          2092:                if (tt->base == PTR && Pptr(tt)->typ->base != FCT)
        !          2093:                        error('w',"P toF cast toP to nonF");
        !          2094:                break;
        !          2095:        case OVERLOAD:
        !          2096:        over:
        !          2097:                error("cast of overloaded");
        !          2098:                goto any;
        !          2099:        }
        !          2100: 
        !          2101: //error('d',"tt %t",tt);
        !          2102:        switch (tt->base) {
        !          2103:        case PTR:
        !          2104:                if (Pptr(tt)->typ->base==FCT && Pptr(tt)->memof) {
        !          2105:                        if (etp->base!=PTR
        !          2106:                        || Pptr(etp)->typ->base!=FCT
        !          2107:                        || Pptr(etp)->memof==0)
        !          2108:                                error("cast toP toM %t",tt);
        !          2109:                        else {  // adjust delta in MI case
        !          2110:                                // for the moment just suppress the cast
        !          2111:                                // all pmfs are the same to cc
        !          2112: /*
        !          2113:                                Pclass c1 = Pptr(tt)->memof;
        !          2114:                                Pclass c2 = Pptr(etp)->memof;
        !          2115: */
        !          2116:                                ptom_cast = 1;
        !          2117:                                tp2 = void_type;
        !          2118:                        }
        !          2119:                }
        !          2120: 
        !          2121:                switch (etp->base) {
        !          2122:                case COBJ:
        !          2123:                        error("cannot castCO toP");
        !          2124:                        break;
        !          2125:                case FCT:
        !          2126:                        e1 = new expr(G_ADDROF,0,e1);
        !          2127:                        bound = b;
        !          2128:                        e1 = e1->typ(tbl);
        !          2129:                        bound = 0;
        !          2130:                        if (e1->base == CAST)
        !          2131:                                pmf = 1;
        !          2132:                        else
        !          2133:                                break;
        !          2134:                        // no break;
        !          2135: 
        !          2136:                case PTR:
        !          2137:                {       Pname cn = Pptr(tt)->typ->is_cl_obj();
        !          2138:                        if (cn) {
        !          2139:                                Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1);
        !          2140: 
        !          2141:                                if (x == e1) {
        !          2142:                                        PERM(tt);
        !          2143:                                        e1 = new cast(tt,e1);
        !          2144:                                        e1->i2 = i2;
        !          2145:                                }
        !          2146:                                else
        !          2147:                                        e1 = x;
        !          2148:                        }
        !          2149:                        if (pmf) {
        !          2150:                                while(tt->base == TYPE)
        !          2151:                                        tt = Pbase(tt)->b_name->tp;
        !          2152: 
        !          2153:                                switch (tt->base) {
        !          2154:                                case PTR:
        !          2155:                                        if (Pptr(tt)->memof) break;
        !          2156:                                default:
        !          2157:                                        error("%t cast to%t (%t is not aP toM)",e1->tp,tp2,tp2);
        !          2158:                                }
        !          2159:                        }
        !          2160:                }
        !          2161:                }
        !          2162:                break;
        !          2163: 
        !          2164:        case RPTR:              // (x&)e: pretend e is an x
        !          2165:        {       Ptype er = etp;
        !          2166:                Ptype cr = tt;
        !          2167:                do {
        !          2168:                        if (er = er->is_ptr_or_ref()) er = Pptr(er)->typ;
        !          2169:                        if (cr = cr->is_ptr_or_ref()) cr = Pptr(cr)->typ;
        !          2170:                } while (er && cr);
        !          2171:                int pp = er!=0; //      if `e' is a suitable pointer cast it:
        !          2172:                                //      (x&)e => (x*)e, otherwise
        !          2173:                                //      (x&)e => *(x*)&e
        !          2174: // error('d',"rptr tt %t e1->base %k e1->tp %t",tt,e1->base,e1->tp);
        !          2175:        //      if (Pptr(tt)->typ->tsizeof()>etp->tsizeof()) goto zse;
        !          2176:        // we need to be able to ``raise the type'' from base to derived
        !          2177:        //      if (etp->is_cl_obj() && Pptr(tt)->typ->is_cl_obj()==0) goto zse;
        !          2178: 
        !          2179:                if (e1->base==G_CM
        !          2180:                || e1->base==CALL
        !          2181:                || e1->base==G_CALL
        !          2182:                || e1->lval(0))
        !          2183:                        ;
        !          2184:                else if (e1->tp->tconst()) {
        !          2185:                                // casting away const
        !          2186:                                // should be an error
        !          2187:                                // but ANSI says OK so I chicken out
        !          2188:                                // to be able to compile strtok(), etc.
        !          2189:                        if (warning_opt && Pptr(tt)->typ->tconst()==0)
        !          2190:                                error('w',"const cast away:%t->%t",e1->tp,tp2);
        !          2191: 
        !          2192:                }
        !          2193:                else
        !          2194:                        error("cannot cast%t to%t",etp,t);
        !          2195: //error('d',"e1 %k %t %d",e1->base,e1->tp,pp);
        !          2196:                if (pp == 0) e1 = e1->address();        // *(x*)&e
        !          2197:                tp = t;
        !          2198: 
        !          2199:                // do proper pointer manipulation for multiple inheritance
        !          2200:                Pname cn = Pptr(tt)->typ->is_cl_obj();
        !          2201:                if (cn) {
        !          2202:                        Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1);
        !          2203: 
        !          2204:                        if (x == e1) {
        !          2205:                                PERM(tt);
        !          2206:                                e1 = new cast(tt,e1);
        !          2207:                                e1->i2 = i2;
        !          2208:                        }
        !          2209:                        else
        !          2210:                                e1 = x;
        !          2211:                }
        !          2212: 
        !          2213:                return pp ? this : contents();
        !          2214: //     zse:
        !          2215: //             error("cannot cast%t to%t",etp,t);
        !          2216: //             tp2 = tt = any_type;
        !          2217: //             break;
        !          2218:        }
        !          2219:        case COBJ:
        !          2220:                base = VALUE;   // (x)e => x(e): construct an x from e
        !          2221:                e1 = new expr(ELIST,e1,0);
        !          2222:                return typ(tbl);
        !          2223: 
        !          2224:        case CHAR:
        !          2225:        case INT:
        !          2226:        case SHORT:
        !          2227:        case LONG:
        !          2228:                switch (etp->base) {
        !          2229:                case FCT:
        !          2230:                        e1 = new expr(ADDROF,0,e1);
        !          2231:                        e1 = e1->typ(tbl);
        !          2232:                        //etp = e1->tp;
        !          2233:                case PTR:
        !          2234:                        if(!e1->tp->memptr() && e1->tp->tsizeof()>tt->tsizeof())
        !          2235:                                error("type ``%t'' not large enough for values of ``%t ''",tt,etp);
        !          2236:                        break;
        !          2237:                case COBJ:
        !          2238:                        error("cannot castCO to%k",tt->base);
        !          2239:                        break;
        !          2240:                }       
        !          2241:                break;
        !          2242: 
        !          2243:        case FLOAT:
        !          2244:        case DOUBLE:
        !          2245:        case LDOUBLE:
        !          2246:                switch (etp->base) {
        !          2247:                case FLOAT:
        !          2248:                case DOUBLE:
        !          2249:                case LDOUBLE:
        !          2250:                case CHAR:
        !          2251:                case INT:
        !          2252:                case SHORT:
        !          2253:                case LONG:
        !          2254:                case EOBJ:
        !          2255:                case ZTYPE:
        !          2256:                        break;
        !          2257:                default:
        !          2258:                        error("cannot cast ``%t '' to ``%t''",etp,tt);
        !          2259:                        break;
        !          2260:                }       
        !          2261:                break;
        !          2262: 
        !          2263:        case FCT:
        !          2264:                error("cannot cast toFT");
        !          2265:                break;
        !          2266:        }
        !          2267: 
        !          2268:        tp = t;
        !          2269: 
        !          2270:        if (e1->base==ILIST && ptom_cast==0) { // pointer to member constant
        !          2271:                Pexpr ee = e1->e1;      // ELIST
        !          2272:                int i;
        !          2273:                switch (ee->e2->base) {
        !          2274:                case IVAL:
        !          2275:                        i = int(ee->e2->i1);
        !          2276:                        break;
        !          2277:                case ZERO:
        !          2278:                        i = 0;
        !          2279:                }
        !          2280: 
        !          2281:                if (i<0)
        !          2282:                        e1 = e1->e2;    // just the function
        !          2283:                else
        !          2284:                        e1 = ee->e2;    // just the index
        !          2285:                return this;
        !          2286:        }
        !          2287: 
        !          2288:        if (etp->base==PTR && Pptr(etp)->memof && Pptr(etp)->typ->base==FCT) {
        !          2289:                Pclass cl = Pptr(etp)->memof;
        !          2290: 
        !          2291:                if (Pptr(tt)->memof==0 && b == 0 ) {
        !          2292:                        Pexpr y = new mdot("f",e1);
        !          2293:                        y->i1 = 9;
        !          2294:                        y = new cast(tt,y);
        !          2295:                        if (cl->virt_count && b==0) {
        !          2296:                                // ERROR: no check for side effects
        !          2297:                                Pexpr z = new mdot("i",e1);
        !          2298:                                Pexpr x = new mdot("i",e1);
        !          2299:                                x->i1 = 9;
        !          2300:                                x = new cast(tt,x);
        !          2301:                                z->i1 = 9;
        !          2302:                                Pexpr q = new expr (QUEST,x,y);
        !          2303:                                q->cond = new expr(LE,zero,z);
        !          2304:                                q->tp = tt;
        !          2305:                                delete this;
        !          2306:                                return q;
        !          2307:                        }
        !          2308:                        delete this;
        !          2309:                        return y;
        !          2310:                }
        !          2311:        }
        !          2312: 
        !          2313:        return this;
        !          2314: }
        !          2315: 
        !          2316: Pexpr expr::dovalue(Ptable tbl)
        !          2317: {
        !          2318:        Ptype tt = tp2;
        !          2319:        Pclass cl;
        !          2320:        Pname cn;
        !          2321: 
        !          2322: //error('d',"value %d %t e1 %d e2 %d",tt,tt,e1,e2);
        !          2323:        
        !          2324:        tt->dcl(tbl);
        !          2325: 
        !          2326:        while(tt->base == TYPE)
        !          2327:                tt = Pbase(tt)->b_name->tp;
        !          2328: 
        !          2329:        switch (tt->base) {
        !          2330:        case EOBJ:
        !          2331:        default:
        !          2332:                if (e1 == 0) {
        !          2333:                        error("value missing in conversion to%t",tt);
        !          2334:                        return dummy;
        !          2335:                }
        !          2336:                base = CAST;
        !          2337:                e1 = e1->e1;    // strip ELIST
        !          2338:                return typ(tbl);
        !          2339: 
        !          2340:        case CLASS:
        !          2341:                cl = Pclass(tt);
        !          2342:                tp2 = Pptr(cl->this_type)->typ;
        !          2343:                break;
        !          2344: 
        !          2345:        case COBJ:
        !          2346:                cn = Pbase(tt)->b_name;
        !          2347:                cl = Pclass(cn->tp);
        !          2348:        }
        !          2349: 
        !          2350: //error('d',"e1 %k e1->e2 %k",e1->base,e1?e1->e2->base:0);
        !          2351:        if (e1 && e1->e2==0) {          // single argument
        !          2352:                if (e1->e1->base==ELIST) e1->e1 = e1->e1->e1;   // spurious elist
        !          2353:                e1->e1 = e1->e1->typ(tbl);
        !          2354:                if (tt->base==COBJ) {
        !          2355:                        Pexpr x = try_to_coerce(tt,e1->e1,"type conversion",tbl);
        !          2356:                        if (x) return x;
        !          2357:                }
        !          2358: 
        !          2359:                Pname acn = e1->e1->tp->is_cl_obj();
        !          2360: //error('d',"acn %n %d",acn,cl->has_itor());
        !          2361:                if (acn && cl->has_itor()==0) {
        !          2362:                        Pclass acl = Pclass(acn->tp);
        !          2363:                        int hb = acl->has_base(cl);
        !          2364: 
        !          2365:                        if (acl==cl || hb) {
        !          2366:                                vcllist->clear();
        !          2367:                                vcllist=0;
        !          2368:                                if (1<is_unique_base(acl,cl->string,0)) error("ambiguous assignment to base %t",cl);
        !          2369:                                Pexpr ee = e1->e1;
        !          2370:                                if (ee->base == ELIST) ee = ee->e1;     // ???
        !          2371:                                if (hb) {       // ee => *(tp2*)&ee
        !          2372:                                                // remember = may be overloaded
        !          2373: //error('d',"hb %k %t %d",ee->base,ee->tp,ee->lval(0));
        !          2374:                                        ignore_const++;
        !          2375:                                        if (ee->lval(0)==0) {
        !          2376:                                                Pname tmp = make_tmp('T',ee->tp,tbl);
        !          2377:                                                ee = init_tmp(tmp,ee,tbl);
        !          2378:                                                ee = new expr(G_CM,ee,tmp->address());
        !          2379:                                        }
        !          2380:                                        else
        !          2381:                                                ee = ee->address();
        !          2382:                                        ignore_const--;
        !          2383:                                        ee = new texpr(CAST,new ptr(PTR,tp2),ee); //new cast(new ptr(PTR,tp2),ee);
        !          2384:                                        ee = ee->contents();
        !          2385:                                        ee->typ(tbl);
        !          2386:                                }
        !          2387: 
        !          2388:                                if (e2) {       // x(x_obj) => e2=x_obj
        !          2389:                                        base = ASSIGN;
        !          2390:                                        e1 = e2;
        !          2391:                                        e2 = ee;
        !          2392:                                        tp = tp2;
        !          2393:                                        return this;
        !          2394:                                }
        !          2395:                                return ee;      // strip ELIST: x(x_obj) => x_obj
        !          2396:                        }
        !          2397:                }
        !          2398:        }
        !          2399: 
        !          2400: 
        !          2401:        /* x(a) => obj.ctor(a); where e1==obj */
        !          2402:        Pname ctor = cl->has_ctor();
        !          2403:        if (ctor == 0) {
        !          2404:                error("cannot make a%t",cl);
        !          2405:                return dummy;
        !          2406:        }
        !          2407: 
        !          2408: // error('d',"e2 %k",e2?e2->base:0);
        !          2409: // error('d',"refd: %d const_ptr: %d", refd, const_ptr);
        !          2410:        if (e2 == 0) {          // x(a) => x temp; (temp.x(a),temp)
        !          2411: /* incomplete condition
        !          2412:                if ( refd && const_ptr == 0) {
        !          2413:                        if ( tbl == gtbl ) {
        !          2414:                                error("Ir forG non-constCR not an lvalue");
        !          2415:                        }
        !          2416:                        else    
        !          2417:                        if (strict_opt) 
        !          2418:                                error("Ir for non-constCR not an lvalue");
        !          2419:                        else
        !          2420:                        if (warning_opt) 
        !          2421:                                error('w', "Ir for non-constR not an lvalue (anachronism)");
        !          2422:                        }
        !          2423: */
        !          2424:        
        !          2425:                no_sti = 1;
        !          2426:                Pname n = make_tmp('V',tp2,tbl);
        !          2427:                no_sti = 0;
        !          2428:                n->assign();
        !          2429:                if (tbl == gtbl) n->dcl_print(0);       // a hack
        !          2430:                Pexpr c = call_ctor(tbl,n,ctor,e1,DOT);
        !          2431:                c = new expr(G_CM,c,n);
        !          2432:                c->tp = n->tp;
        !          2433: //error('d',"tp1 %t",c->tp);
        !          2434:                return c;
        !          2435:        }
        !          2436:        else {
        !          2437:                Pexpr c = call_ctor(tbl,e2,ctor,e1,DOT);
        !          2438:                c = new expr(DEREF,c,0); // deref value returned by constructor
        !          2439:                c->tp = c->e1->tp;
        !          2440: //error('d',"tp2 %t",c->tp);
        !          2441:                return c;
        !          2442:        }
        !          2443: }
        !          2444: 

unix.superglobalmegacorp.com

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