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

1.1     ! root        1: /*ident        "@(#)ctrans:src/find.c  1.6" */
        !             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) 1986 AT&T, Inc. All Rights Reserved
        !             8:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
        !             9: 
        !            10: find.c:
        !            11: 
        !            12:        name lookup and visibility checks
        !            13: 
        !            14: *******************************************************************/
        !            15: 
        !            16: #include "cfront.h"
        !            17: 
        !            18: Pname undef(Pname n, Ptable tbl, TOK f)
        !            19: {
        !            20:        switch (f) {
        !            21:        case CCON:
        !            22:                error("illegalF call: explicit call ofK %s()",n->string);
        !            23:                break;
        !            24:        case 0:         error("%nU",n);                 break;
        !            25:        case CALL:      error("UF%n called",n);         break;
        !            26:        case REF:
        !            27:        case DOT:       error("M%nU",n);                break;
        !            28:        case ADDROF:    error("address ofU%n",n);       break;
        !            29:        }
        !            30: 
        !            31:        if (tbl == gtbl) {
        !            32:                Pname nn = tbl->insert(n,0);
        !            33:                if (f == CALL) {
        !            34:                        nn->tp = new fct(defa_type,0,0);
        !            35:                        nn->n_sto = nn->n_scope = EXTERN;
        !            36:                }
        !            37:                else
        !            38:                        nn->tp = any_type;
        !            39:                delete n;
        !            40:                return nn;
        !            41:        }
        !            42:        
        !            43:        n->n_table = tbl;
        !            44:        n->tp = any_type;
        !            45:        return n;
        !            46: }
        !            47: 
        !            48: 
        !            49: 
        !            50: static int mptr;       // &C::m
        !            51: static Pname me;       // name of fct requesting access to name using find_name()
        !            52: static Pfct mef;       // fct requesting access to name using find_name()
        !            53: Pclass tcl;            // class of original ``this''
        !            54: Pclass mec;            // class requesting access to name using find_name()
        !            55: int mex;
        !            56: 
        !            57: Ptable lcl_tbl = 0;    // handle local function reference of local const for dimen size
        !            58: 
        !            59: 
        !            60: Pexpr find_name(Pname n, Pclass cl, Ptable tbl, int f, Pname m)
        !            61: /*
        !            62:        in function ``m'' find the true name for "n",
        !            63:        implicitly define if undefined
        !            64: 
        !            65:        f==CALL:        n()             cl == cc->cot
        !            66:        f==REF:         p->n            cl == class of *p
        !            67:        f==DOT:         obj.n           cl == class of obj
        !            68:        f==ADDROF:      &n              cl == cc->cot
        !            69:        f==0            n               (none of the above)
        !            70: 
        !            71:        "tbl" defines local scope (block or global)
        !            72: 
        !            73: */
        !            74: {
        !            75:        if ( n == 0 ) error('i',"find_name(n==0,cl==%t,tbl==%d,f==%k,m==%n)",cl,tbl,f,m);
        !            76:        Pname q = n->n_qualifier;
        !            77:        char* s = n->string;
        !            78:        Pexpr ee;
        !            79:        DB( if(Ddebug>=3) {
        !            80:                error('d',"find_name %s::%s cl %t",q?q->string:"",s,cl);
        !            81:                error('d',"     f %d m %n",f,m);
        !            82:                if(q&&q->tp&&q->tp->base==COBJ)
        !            83:                        fprintf(stderr," -- cb==%d\n",Pclass(q->tp)->c_body);
        !            84:        });
        !            85: 
        !            86:        tcl = cl;
        !            87: 
        !            88:        //if (n) {
        !            89:                mex = 1;
        !            90:                if (me = m) {
        !            91:                        mef = Pfct(me->tp);
        !            92:                         if (mef->base!=FCT) 
        !            93:                                 error('i',"mef %d %k",mef,mef->base);
        !            94:                        mec = mef->memof;
        !            95:                }
        !            96:                else {
        !            97:                        mef = 0;
        !            98:                        mec = cl;
        !            99:                }
        !           100:        //}
        !           101:        //else
        !           102:        //      mex = 0;
        !           103: 
        !           104:        if (n->base == MDOT) error('i',"find (mdot %n)",n);
        !           105: 
        !           106:        if (n->n_table) { me = 0; return n; }
        !           107: 
        !           108: //error('d',"q %n %t f %k",q,q?q->tp:0,f);
        !           109:        if (q) {                        // qualified name:      q::s
        !           110: 
        !           111:                if (q == sta_name) {    // explicitly global:   ::s
        !           112:                        Pname nn = gtbl->look(s,0);
        !           113:                        if (nn == 0) { me = 0; return undef(n,gtbl,f); }
        !           114:                        nn->use();
        !           115:                        delete n;
        !           116:                        me = 0;
        !           117:                        return nn;
        !           118:                }
        !           119: 
        !           120:                {
        !           121:                  Pname aq = q; // actual q
        !           122:                  while ( aq->tp->base == TYPE ) aq = Pbase(aq->tp)->b_name;
        !           123:                  if (aq->tp->base != COBJ) {
        !           124:                    error("Qr%nnot aCN",q);
        !           125:                    me = 0;
        !           126:                    return undef(n,gtbl,f);
        !           127:                  }
        !           128:                  q = aq;
        !           129:                }
        !           130:                Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp);
        !           131: 
        !           132:                Pclass bcl = cl;
        !           133: 
        !           134:                if (cl==0 || f==ADDROF)
        !           135:                        bcl = cl = qcl; // Pclass(Pbase(q->tp)->b_name->tp);
        !           136:                else {
        !           137:                //      if (strcmp(q->string,cl->string)) {     // really a base?
        !           138:                //              bcl = cl->is_base(q->string);
        !           139:                        if (strcmp(qcl->string,cl->string)) {   // really a base?
        !           140:                                bcl = cl->is_base(qcl->string);
        !           141:                                if (bcl == 0) {
        !           142:                                        if (f==REF || f==DOT) {
        !           143:                                                error("%s is not aBC of %t",q->string,cl);
        !           144:                                                me = 0;
        !           145:                                                return undef(n,cl->memtbl,7);
        !           146:                                        }
        !           147:                                        goto sss;
        !           148:                                }
        !           149:                                // else try in base or for static
        !           150:                        }
        !           151:                }
        !           152: 
        !           153:                if (f == ADDROF) mptr = 1;              // &C::m
        !           154:                ee = cl->find_name(s,bcl==cl?0:bcl);    // really a member?
        !           155:                mptr = 0;
        !           156: 
        !           157:                if (ee == 0) {
        !           158:                sss:
        !           159: //error('d',"sss %k",f);
        !           160:                        Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp);
        !           161:                        Pname nn=qcl->memtbl->look(s,0);
        !           162: 
        !           163:                        if ((f==0) && (nn && nn->tp && nn->tp->base != EOBJ && nn->tp->base!=FCT) && (nn->n_stclass != STATIC) && (q && q->tp && q->tp->base!=FCT && q->tp->base != OVERLOAD))
        !           164:                        {
        !           165:                                error("O missing for %n",q);
        !           166:                                if (n) delete n;
        !           167:                                me = 0;
        !           168:                                return q;
        !           169:                        }
        !           170:                        
        !           171:                        if (f!=REF && f!=DOT) {
        !           172:                                // try for static member of other class:
        !           173:                                Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp);
        !           174:                                mptr = 1;
        !           175:                                if ( cl && cl->csu == ANON ) {
        !           176:                                        mec = (cc-1)->cot;
        !           177:                                        ee = qcl->find_name(s,qcl);
        !           178:                                } else
        !           179:                                        ee = qcl->find_name(s,qcl);
        !           180:                                mptr = 0;
        !           181:                                if (ee && ee->base==NAME) {
        !           182:                                //      switch (ee->tp->base) {
        !           183:                                //      case FCT:
        !           184:                                //      case OVERLOAD:
        !           185:                                //              break;
        !           186:                                //      default:
        !           187:                                                delete n;
        !           188:                                                me = 0;
        !           189:                                                return ee;
        !           190:                                //      }
        !           191:                                }
        !           192:                        }
        !           193:                        error("QdN%n::%n not found in %t",q,n,cl);
        !           194:                        me = 0;
        !           195:                        return undef(n,bcl?bcl->memtbl:cl->memtbl,7);
        !           196:                }
        !           197: 
        !           198:                if (ee->base==REF && ee->e1==0) {       // &C::f, no ``this''
        !           199: //error('d',"ee %k %d f %k",ee->base,ee->e1,f);
        !           200:                        switch (f) {
        !           201:                        case 0:
        !           202:                        case CALL:      //SSS
        !           203:                                {       Pexpr mm = ee->mem;
        !           204:                                        while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
        !           205:                                        if (mm->base==NAME)
        !           206:                                                switch (mm->tp->base) {
        !           207:                                                case FCT:
        !           208:                                                case OVERLOAD:
        !           209:                                                        goto addrof;
        !           210:                                                default:
        !           211:                                                        if (Pname(mm)->n_stclass == STATIC) goto addrof;
        !           212:                                                }
        !           213:                                }
        !           214:                                error("O orOP missing forM%n",n);
        !           215:                                        
        !           216:                        case ADDROF:
        !           217:                        addrof:
        !           218:                                Pexpr x = ee;
        !           219:                                ee = ee->mem;
        !           220:                                delete x;
        !           221:                        case REF:
        !           222:                        case DOT:
        !           223:                                break;
        !           224:                        default:
        !           225:                                error("QdN%n::%n used in nonC context",q,n);
        !           226:                        }
        !           227:                }
        !           228: 
        !           229:                delete n;
        !           230:                me = 0;
        !           231:                return ee;
        !           232:        }
        !           233: 
        !           234:        if (f!=DOT && f!=REF) { // not .s or ->s: look for local, global, and member
        !           235: 
        !           236:                Pname nn = tbl->look(s,0);
        !           237:                if (nn) {       // local, global, or member
        !           238:                        if (nn->n_table->t_name) {      // global or member
        !           239:                                if (cl) {               // might be member
        !           240:                                        if ((ee = cl->find_name(s,0))==0 &&
        !           241:                                                cl->in_class) 
        !           242:                                        { // nested class
        !           243:                                                Pclass nstd_cl = cl->in_class;
        !           244:                                                for (; nstd_cl; nstd_cl=nstd_cl->in_class) 
        !           245:                                                {
        !           246: // error( 'd', "find_name( %s ): nested class %t",s,nstd_cl ); 
        !           247:                                                        if (ee=nstd_cl->find_name(s,0)) 
        !           248:                                                        {
        !           249:                                                                if ( cl->nested_sig == 0 ) {
        !           250:                                                                        error('w',"%s, accessed within nestedC%t, is visible bothGly and within enclosingC%t -- using %n (anachronism)", s, cl, nstd_cl, nn );
        !           251:                                                                        ee = 0;
        !           252:                                                                }
        !           253:                                                                break;
        !           254:                                                        }
        !           255:                                                }       
        !           256:                                        } // nested class
        !           257:                                
        !           258:                                        if ( ee ) 
        !           259:                                        {  // class member name
        !           260:                                                if (ee->base==REF && ee->e1==0 )
        !           261:                                                {
        !           262:                                                        Pexpr mm = ee->mem;
        !           263:                                                        while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
        !           264:                                                        if (mm->base==NAME)
        !           265:                                                                switch (mm->tp->base) {
        !           266:                                                                default:
        !           267:                                                                        if (Pname(mm)->n_stclass != STATIC)
        !           268:                                                                                break;
        !           269:                                                                case FCT:
        !           270:                                                                case OVERLOAD:
        !           271:                                                                        delete n;
        !           272:                                                                        me = 0;
        !           273:                                                                        return mm;
        !           274:                                                                }
        !           275:                                                        error("O orOP missing for%n",Pref(ee)->mem);
        !           276:                                                }
        !           277:                                                delete n;
        !           278:                                                me = 0;
        !           279:                                                return ee;
        !           280:                                          }  // if ee
        !           281:                                }  // if cl
        !           282:                        } // else local, global, or member
        !           283: 
        !           284:                        nn->use();
        !           285:                        delete n;
        !           286:                        me = 0;
        !           287:                        return nn;
        !           288:                }
        !           289: 
        !           290:                if (cl) {
        !           291:                        if ( cl->csu == ANON ) {
        !           292:                                mec = (cc-1)->cot;
        !           293:                                ee = (cc-1)->cot->find_name(s,0);
        !           294:                        } else
        !           295:                                ee = cl->find_name(s,0);
        !           296:                        if (ee) {
        !           297:                        if (ee->base==REF && ee->e1==0) {
        !           298:                                Pexpr mm = ee->mem;
        !           299:                                while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
        !           300:                                if (mm->base==NAME)
        !           301:                                        switch (mm->tp->base) {
        !           302:                                        default:
        !           303:                                                if (Pname(mm)->n_stclass != STATIC)
        !           304:                                                        break;
        !           305:                                        case FCT:
        !           306:                                        case OVERLOAD:
        !           307:                                                delete n;
        !           308:                                                me = 0;
        !           309:                                                return mm;
        !           310:                                        
        !           311:                                        }
        !           312:                                error("O orOP missing for%n",Pref(ee)->mem);
        !           313:                        }
        !           314:                                delete n;
        !           315:                                me = 0;
        !           316:                                return ee;
        !           317:                        }
        !           318:                }
        !           319: 
        !           320:                if ( lcl_tbl && (nn=lcl_tbl->look(s,0)) ) {
        !           321:                        nn->use();
        !           322:                        delete n;
        !           323:                        me = 0;
        !           324:                        return nn;
        !           325:                }
        !           326: 
        !           327:                if (nn = gtbl->look(s,0)) {     // global
        !           328:                        nn->use();
        !           329:                        delete n;
        !           330:                        me = 0;
        !           331:                        return nn;
        !           332:                }
        !           333: 
        !           334:                me = 0;
        !           335:                return undef(n,gtbl,f);
        !           336:        }
        !           337: 
        !           338:        if (ee = cl->find_name(s,cl)) { // .s or ->s
        !           339:                delete n;
        !           340:                me = 0;
        !           341:                return ee;
        !           342:        }
        !           343: 
        !           344:        if(!strcmp(s,cl->string)) {
        !           345:                me = 0;
        !           346:                return undef(n,gtbl,CCON);
        !           347:        }
        !           348: 
        !           349:        me = 0;
        !           350:        return undef(n,gtbl,f);
        !           351: }
        !           352: 
        !           353: int classdef::check_dup(Pclass cl, TOK bb)
        !           354: /*
        !           355:         see if cl is a base of this; return 0 if no clash
        !           356: */
        !           357: {
        !           358:        for (Pbcl b = baselist; b; b=b->next) {
        !           359:                if (cl == b->bclass) {
        !           360:                        if (bb!=VIRTUAL) {
        !           361:                                if (b->base==VIRTUAL)
        !           362:                                        error('w',"%t inaccessible because of virtual%t in%t",cl,cl,this);
        !           363:                                else
        !           364:                                        error('w',"%t inaccessible because of%t in%t",cl,cl,this);
        !           365:                                return 1;
        !           366:                        }
        !           367:                        else if (b->base!=VIRTUAL) {
        !           368:                                error('w',"virtual %t inaccessible because of%t in%t",cl,cl,this);
        !           369:                                return 1;
        !           370:                        }
        !           371:                }
        !           372:                if (b->bclass->check_dup(cl,bb)) return 1;
        !           373:        }
        !           374:        return 0;
        !           375: }
        !           376: 
        !           377: 
        !           378: int Nvis;
        !           379: TOK Nvirt;
        !           380: TOK ppbase;
        !           381: 
        !           382: Pclass classdef::is_base(char* s)
        !           383: /*
        !           384:        is "s" a public base class of this?
        !           385: */
        !           386: {
        !           387: //error('d',"%s->is_base(%s) %k",string,s,ppbase);
        !           388:        TOK pp = ppbase;
        !           389:        for (Pbcl b = baselist; b; b=b->next) {
        !           390: /*
        !           391:                if (b->ppp!=PUBLIC
        !           392:                && cc->cot!=this
        !           393:                && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
        !           394:                        ppbase = b->ppp<pp?pp:b->ppp;   // PUBLIC<PROTECTED<PRIVATE
        !           395: */
        !           396:                if (strcmp(s,b->bclass->string) == 0) {
        !           397:                if (b->ppp!=PUBLIC
        !           398:                && cc->cot!=this
        !           399:                && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
        !           400:                        ppbase = b->ppp<pp?pp:b->ppp;   // PUBLIC<PROTECTED<PRIVATE
        !           401:                        Nvirt = b->base;
        !           402:                        return b->bclass;
        !           403:                }
        !           404:                else {
        !           405:                        Pclass bc = b->bclass->is_base(s);
        !           406:                        if (bc) {
        !           407:                if (b->ppp!=PUBLIC
        !           408:                && cc->cot!=this
        !           409:                && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
        !           410:                        ppbase = b->ppp<pp?pp:b->ppp;   // PUBLIC<PROTECTED<PRIVATE
        !           411:                                return bc;
        !           412:                        }
        !           413:                }
        !           414:        }
        !           415:        ppbase = pp;
        !           416:        return 0;
        !           417: }
        !           418: 
        !           419: bit classdef::has_base(Pclass cl)
        !           420: /*
        !           421:        is "cl" a base of this?
        !           422: */
        !           423: {
        !           424: // error('d', "%t->has_base( %t ) cc->cot: %t", this, cl, cc->cot?cc->cot:0 );
        !           425: 
        !           426:        if (this == 0) return 0;
        !           427:        for (Pbcl b = baselist; b; b=b->next) {
        !           428: // error('d', "b: %t ppp: %k", b->bclass, b->ppp );
        !           429:                if (b->bclass==cl) {
        !           430:                        if (b->ppp!=PUBLIC
        !           431:                        && cc->cot!=this
        !           432:                        && (cc->nof==0 ||
        !           433:                                this->has_friend(Pfct(cc->nof->tp))==0) 
        !           434:                        && this->has_friend(cc->cot)==0)
        !           435:                                Nvis = 1;       // no standard coercion
        !           436:                        Nvirt = b->base;
        !           437:                        return 1;
        !           438:                }
        !           439:                if (b->bclass->has_base(cl)) return 1;
        !           440:        }
        !           441:        return 0;
        !           442: }
        !           443: 
        !           444: int Noffset;
        !           445: Pexpr Nptr;
        !           446: char *Nalloc_base;
        !           447: clist* vcllist;
        !           448: 
        !           449: int clist::onlist(Pclass c)
        !           450: {
        !           451:        for (clist* p = this; p; p = p->next)
        !           452:                if (p->cl == c) return 1;
        !           453:        return 0;
        !           454: }
        !           455: 
        !           456: void clist::clear()
        !           457: {
        !           458:        if (this == 0) return;
        !           459:        clist* p = next;
        !           460:        while (p) {
        !           461:                clist* q = p->next;
        !           462:                delete p;
        !           463:                p = q;
        !           464:        };
        !           465:        delete this;
        !           466: }
        !           467: 
        !           468: Pbcl Nvbc_alloc;
        !           469: int is_unique_base(Pclass cl, char* s, int offset, int in_base )
        !           470: /*
        !           471:        is "s" a unique base class of this?
        !           472: */
        !           473: {
        !           474:        int i = 0;
        !           475:        static Pclass priSeen = 0;
        !           476: // error('d',"is_unique_base(cl: %t, s: %s,%d,%d)",cl,s,offset,in_base);
        !           477:        for (Pbcl b = cl->baselist; b; b=b->next) {
        !           478:                int no = 0;
        !           479:                if (b->base!=VIRTUAL)
        !           480:                        no = offset + b->obj_offset;
        !           481:                else if (in_base)
        !           482:                        continue;
        !           483:                if (strcmp(s,b->bclass->string) == 0) {
        !           484:                        Noffset = no;
        !           485:                        i++;
        !           486:                        if ((b->ppp!=PUBLIC || priSeen )
        !           487:                                && (cc->cot!=cl || cc->cot != priSeen )
        !           488:                                && (cc->nof==0 || cl->has_friend(Pfct(cc->nof->tp))==0)
        !           489:                                        || (priSeen && priSeen->has_friend(Pfct(cc->nof->tp))==0))
        !           490:                                                Nvis = 1;       // no standard coercion
        !           491: 
        !           492:                        if (b->base==VIRTUAL) {
        !           493:                                Nptr = new mdot(s,0);
        !           494:                                if (b->allocated == 0) {
        !           495:                                        Nvbc_alloc = 0;
        !           496:                                        Nalloc_base = cl->has_allocated_base(s);
        !           497:                                }
        !           498:                        }
        !           499:                }
        !           500:                else {
        !           501:                        if (b->base==VIRTUAL) {
        !           502:                                if (vcllist->onlist(b->bclass) )continue;
        !           503:                                vcllist = new clist(b->bclass,vcllist);
        !           504:                        }
        !           505: 
        !           506:                        Pclass clscope = 0;
        !           507:                        if ( cc && cc->c_this ) {
        !           508:                                Ptype t = Pptr(cc->c_this->tp)->typ;
        !           509:                                clscope = Pclass(Pbase(t)->b_name->tp);
        !           510:                        }
        !           511: // error('d', "cl: %t %d clscope: %t %d", cl, cl, clscope, clscope);
        !           512:                        if (b->ppp != PUBLIC && 
        !           513:                                cl != clscope && priSeen == 0 ) priSeen = cl;
        !           514: 
        !           515:                        int ii = is_unique_base(b->bclass,s,no,1);
        !           516:                        if (in_base == 0) priSeen = 0;
        !           517: // error('d',"base %t i %d ii %d",b->bclass,i,ii);
        !           518: // error('d',"base %t %k allocated: %d", b->bclass, b->base, b->allocated);
        !           519:                        i += ii;
        !           520:                        if (ii==1 && b->base==VIRTUAL) {
        !           521:                                Nptr = new mdot(b->bclass->string,0);
        !           522:                                if (b->allocated == 0) {
        !           523:                                        Nvbc_alloc = 0;
        !           524:                                        Nalloc_base = cl->has_allocated_base(b->bclass->string);
        !           525:                                }
        !           526:                        }
        !           527:                }
        !           528:        }
        !           529: 
        !           530:        return i;
        !           531: }
        !           532: 
        !           533: /*
        !           534: int classdef::has_allocated_base(Pclass bcl)
        !           535: 
        !           536:        search the list of !first base classes for this virtual base
        !           537:        space will have been allocated in !first bases for virtual bases
        !           538:        declared in !first classes
        !           539: 
        !           540:        in addition bcl may bave been specified explicitly as a base
        !           541: 
        !           542: {
        !           543:        int off;
        !           544:        for (Pbcl l = baselist; l; l=l->next) {
        !           545:                if (l->base == VIRTUAL) continue; // another non-allocated virtual base
        !           546:                if (l==baselist) continue;      // first base
        !           547: 
        !           548:                Pclass bc = l->bclass;
        !           549:                off = l->obj_offset;
        !           550: 
        !           551:                for (Pbcl ll = bc->baselist; ll; ll=ll->next) {
        !           552:                        // cannot share non-virtual base
        !           553:                        if (ll->base != VIRTUAL) continue;
        !           554:                        if (ll->bclass==bcl) return off + ll->obj_offset;
        !           555:                }
        !           556:        }
        !           557:        return 0;
        !           558: }
        !           559: */
        !           560: 
        !           561: int classdef::has_allocated_base(Pclass bcl)
        !           562: /*
        !           563:        search the list of base classes for this virtual base
        !           564:        space will be allocated in first virtual version found.
        !           565:        return offset.
        !           566: 
        !           567:        A virtual base cannot have offset 0 (its pointer at least is ahead)
        !           568: */
        !           569: {
        !           570: //error('d',"%t->has_allocated_base(%t) ",this,bcl);
        !           571:        for (Pbcl l = baselist; l; l=l->next) {
        !           572:                if (l->base==VIRTUAL
        !           573:                && l->bclass==bcl
        !           574:                && l->obj_offset)
        !           575:                        return l->obj_offset;
        !           576: 
        !           577:                if (l->base==VIRTUAL || l!=baselist) {
        !           578:                        // allocated as an object,
        !           579:                        // not unravelled as a set of members
        !           580:                        int i = l->bclass->has_allocated_base(bcl);
        !           581:                        if (i) return l->obj_offset + i;
        !           582:                }
        !           583:        }
        !           584:        return 0;
        !           585: }
        !           586: 
        !           587: char *classdef::has_allocated_base(char *str) 
        !           588: /*
        !           589:  *     str is an unallocated virtual base class of this
        !           590:  *     return the name of the second or subsequent base class 
        !           591:  *             containing the member ``struct str *P<str>''
        !           592:  */
        !           593: {
        !           594: // error('d',"%t::has_allocated_base(%s) baselist: %t",this,str,baselist->bclass);
        !           595:        for (Pbcl l = baselist; l; l=l->next) {
        !           596:                if (l->base == VIRTUAL) {
        !           597:                        if ( l->allocated ) Nvbc_alloc = l; 
        !           598:                        continue; 
        !           599:                }
        !           600: 
        !           601:                Pclass bc = l->bclass;
        !           602:                for (Pbcl ll = bc->baselist; ll; ll=ll->next) {
        !           603:                        if (ll->base != VIRTUAL) continue;
        !           604:                        if (ll->allocated && 
        !           605:                            strcmp( str, ll->bclass->string) == 0 )
        !           606:                                { 
        !           607:                                        if (bc == baselist->bclass) {
        !           608:                                                // NfirstBase=1; 
        !           609:                                                return 0;
        !           610:                                        }
        !           611:                                        return bc->string;
        !           612:                                }
        !           613:                }
        !           614:        }
        !           615:        return 0;
        !           616: }
        !           617: 
        !           618: /*
        !           619: int allocated_base(Pclass cl,Pclass bcl)
        !           620: {
        !           621: static second;
        !           622: int s2 = second;
        !           623:        for (Pbcl l = cl->baselist; l; l=l->next) {
        !           624:                if (l->base==VIRTUAL
        !           625:                && l->bclass==bcl
        !           626:                && l->obj_offset
        !           627:                && (second || l!=cl->baselist)) return (second=s2,1);
        !           628:                int i = allocated_base(l->bclass,bcl);
        !           629:                if (i) return (second=s2,1);
        !           630:                second = 1;
        !           631:        }
        !           632:        second = s2;
        !           633:        return 0;
        !           634: }
        !           635: */
        !           636: Pname vfct(Pclass cl, char* s)
        !           637: /*
        !           638:        Called for each name "s" in a vtbl for "cl"
        !           639:        Find the "s" to go in the vtbl.
        !           640:        The "s" that caused the vtbl entry to be created
        !           641:                is found if nothing else is
        !           642: */
        !           643: {
        !           644:        Pname n = cl->memtbl->look(s,0);
        !           645:        if (n) return n;
        !           646: 
        !           647:        for (Pbcl b = cl->baselist; b; b=b->next) {
        !           648:                Pname nn = vfct(b->bclass,s);
        !           649:                if (nn) {
        !           650: //error('d',"nn %nn",nn);
        !           651:                        if (n && n!=nn) {
        !           652:                                Pclass ncl = Pclass(n->n_table->t_name->tp);
        !           653:                                Pclass nncl = Pclass(nn->n_table->t_name->tp);
        !           654: //error('d',"ncl %t nncl %t",ncl,nncl);
        !           655:                                if (nncl->is_base(ncl->string))
        !           656:                                        n = nn;         // use nn
        !           657:                        }
        !           658:                        else
        !           659:                                n = nn;
        !           660:                }
        !           661:        }
        !           662: 
        !           663:        return n;
        !           664: }
        !           665: 
        !           666: Pexpr rptr(Ptype t, Pexpr p, int offset)
        !           667: /*
        !           668:        return rvalue of offset off pointer:
        !           669:        (t)((char*)p+offset)
        !           670: */
        !           671: {
        !           672:        if ( t == 0 ) error( 'i', "rptr(), t==0 (type passed for cast)" );
        !           673:        Pexpr pp = p;
        !           674: //error('d',"rptr %t %d",t,offset);
        !           675:        if (offset) {
        !           676:                Pexpr i = new ival(offset);
        !           677:        //      pp = new texpr(CAST,Pchar_type,pp);
        !           678:                pp = new cast(Pchar_type,pp);
        !           679:                pp = new expr(PLUS,pp,i);
        !           680:        }
        !           681:        pp = new cast(t,pp);
        !           682:        return pp;
        !           683: }
        !           684: /*
        !           685: Pexpr lptr(Ptype t, Pexpr p, int offset)
        !           686: 
        !           687:        return lvalue of offset off pointer:
        !           688:        *(t*)((char*)p+offset)
        !           689: 
        !           690: {
        !           691:        Pexpr pp = p;
        !           692:        if (offset) {
        !           693:                Pexpr i = new ival(offset);
        !           694:        //      pp = new texpr(CAST,Pchar_type,pp);
        !           695:                pp = new cast(Pchar_type,pp);
        !           696:                pp = new expr(PLUS,pp,i);
        !           697:        }
        !           698:        pp = new cast(t->addrof(),pp);
        !           699:        pp = new expr(DEREF,pp,0);
        !           700:        pp->tp = t;
        !           701:        return pp;
        !           702: }
        !           703: */
        !           704: int friend_check(Pclass start,Pclass stop, Pfct f)
        !           705: /*
        !           706:        is `f' a friend of a class between `start' and `stop'
        !           707:        in a class DAG?
        !           708: */
        !           709: {
        !           710: //error('d',"friend_check(%t,%t)",start,stop);
        !           711:        
        !           712:        if (start->has_friend(f)) return 1;
        !           713:        if (stop == start) return 0;
        !           714:        for (Pbcl b = start->baselist; b; b = b->next) {
        !           715:                if (b->bclass->has_friend(f)) return 1;
        !           716:                if (friend_check(b->bclass,stop,f)) return 1;
        !           717:        }
        !           718:        return 0;
        !           719: }
        !           720: 
        !           721: bit classdef::has_friend(Pfct f)
        !           722: /*
        !           723:        does this class have function "f" as its friend?
        !           724: */
        !           725: {
        !           726: // error('d',"%t->has_friend(%t) %d %d ",this,f,f,f->base);
        !           727: 
        !           728:        for (Plist l=friend_list; l; l=l->l) {
        !           729:                Pname fr = l->f;
        !           730:                Ptype frt = fr->tp;
        !           731: //error('d',"frt %t %d %d",frt,frt,frt->base);
        !           732:                switch (frt->base) {
        !           733:                case FCT:
        !           734:                        if (f == frt) return 1;
        !           735:                        break;
        !           736:                case OVERLOAD:
        !           737:                        l->f = fr = Pgen(frt)->fct_list->f;     // first fct
        !           738:                        if (fr->tp == f) return 1;
        !           739:                case CLASS:
        !           740:                        break;
        !           741:                default:
        !           742:                        error('i',"bad friend %k",fr->tp->base);
        !           743:                }
        !           744:        }
        !           745:        return 0;
        !           746: }
        !           747: 
        !           748: bit classdef::has_friend(Pclass cl)
        !           749: /*
        !           750:        does this class have class "cl" as its friend?
        !           751: */
        !           752: {
        !           753: // error('d',"%t->has_friend(%t) ",this,cl);
        !           754: 
        !           755:        for (Plist l=friend_list; l; l=l->l) {
        !           756:                Pname fr = l->f;
        !           757:                Ptype frt = fr->tp;
        !           758:                switch (frt->base) {
        !           759:                case CLASS:
        !           760: // error('d',"class friend: %t", frt);
        !           761:                        if ((frt == cl) || cl->same_class(Pclass(frt))) 
        !           762:                                return 1;
        !           763:                case FCT:
        !           764:                case OVERLOAD:
        !           765:                        break;
        !           766:                default:
        !           767:                        {error('i',"bad friend %k",frt->base);}
        !           768:                }
        !           769:        }
        !           770:        return 0;
        !           771: }
        !           772: 
        !           773: Pname find_virtual(Pclass cl, Pname s)
        !           774: /*
        !           775:        does ``cl'' have a virtual function ``s'' in some base class
        !           776: */
        !           777: {
        !           778:        for (Pbcl b = cl->baselist; b; b = b->next) {
        !           779:                Pclass bcl = b->bclass;
        !           780:                Pname n;
        !           781:                if (n = bcl->memtbl->look(s->string,0)) {
        !           782: // error('d', "find_virtual: n: %d base: %k", n, n->base );
        !           783:                        if ( n->base == PUBLIC ) // x::foo;
        !           784:                                continue;
        !           785:                        Pfct f = Pfct(n->tp);
        !           786:                        if (f->base == OVERLOAD) {
        !           787:                                for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) {
        !           788:                                        n = gl->f;
        !           789:                                        // if (f != s->tp) continue;
        !           790:                                        // Replaced by:
        !           791:                                        if (n->tp->check(s->tp,VIRTUAL)) continue;
        !           792:                                        if (Pfct(n->tp)->f_virtual) return n;
        !           793:                                }
        !           794:                        }
        !           795:                        // else if (f->f_virtual)
        !           796:                        else if (f->f_virtual && n->tp->check(s->tp,VIRTUAL)==0)
        !           797:                                return n;
        !           798:                }
        !           799:                else if (n = find_virtual(bcl,s))
        !           800:                        return n;
        !           801:        }
        !           802:        return 0;
        !           803: }
        !           804: 
        !           805: Pname dummy_fct;
        !           806: 
        !           807: static int 
        !           808: is_accessible(Pname n, Pclass this_class, bit noCdcl = 0)
        !           809: // 0 means n is not accessible to this_class
        !           810: {
        !           811: // error('d',"is_accessible(%n,%t)", n, this_class
        !           812: // error('d',"%n: %k mef %t",n,n->n_protect,mef);
        !           813: // error('d',"         this_class %d %t",this_class,this_class);
        !           814: // error('d',"         mec  %d %t",mec,mec);
        !           815: // error('d',"         tcl  %d %t",tcl,tcl);
        !           816: // error('d',"mec->has_base(this_class) %d",mec?mec->has_base(this_class):0);
        !           817: // error('d',"tcl->has_base(mec) %d",tcl?tcl->has_base(mec):0);
        !           818: // error('d',"tcl->has_base(this_class) %d",tcl?tcl->has_base(this_class):0);
        !           819: // error('d',"tcl->has_friend(mef) %d",tcl?tcl->has_friend(mef):0);
        !           820: 
        !           821:        if (this_class==mec || 
        !           822:                (mec && this_class->has_friend(mec)) || 
        !           823:                (mef && this_class->has_friend(mef)))
        !           824:                        return 1;
        !           825:        
        !           826:        if ( n->n_protect && tcl ) {
        !           827:                if ( mec ) 
        !           828:                {
        !           829:                        if ( tcl->has_friend(mec) ||
        !           830:                                ( mec->has_base(this_class) && 
        !           831:                                        (tcl==mec || tcl->has_base(mec))))
        !           832:                                                return 1;
        !           833:                }       
        !           834: 
        !           835:                if ( mef ) 
        !           836:                {
        !           837:                        if ( tcl->has_base(this_class) &&
        !           838:                                // && tcl->has_friend(mef))
        !           839:                                friend_check(tcl,this_class,mef))
        !           840:                                        return 1;
        !           841:                }
        !           842:        }
        !           843: 
        !           844:        // call from check_visibility
        !           845:        if ( noCdcl ) return 0; 
        !           846:        
        !           847:        if ( Cdcl && Cdcl->base == NAME && 
        !           848:                Cdcl->n_stclass == STATIC && 
        !           849:                Cdcl->n_initializer && 
        !           850:                Cdcl->n_qualifier ) 
        !           851:        {
        !           852:                Pbase bn = Pbase(Cdcl->n_qualifier->tp);
        !           853:                Pclass cl = Pclass(bn->b_name->tp);
        !           854: 
        !           855:                if ( cl == this_class ||
        !           856:                        (n->n_protect && cl->has_base(this_class)) || 
        !           857:                        cl->has_friend(this_class))
        !           858:                                return 1;
        !           859:        }
        !           860: 
        !           861:        return 0;
        !           862: }
        !           863: 
        !           864: Pexpr classdef::find_name(char* s, Pclass cl, int access_only)
        !           865: /*
        !           866:        look for "s" in "this" class and its base classes
        !           867:        if (cl)
        !           868:                accept only a member of "cl" or "cl"'s base classes
        !           869:                (that is cl::s was seen)
        !           870: 
        !           871:        complicated by hiding rules: private, protected, friend
        !           872:        
        !           873: */
        !           874: {
        !           875: // error('d',"%s->find_name(%s,%s) memtbl %d",string,s,cl?cl->string:"",memtbl);
        !           876:        Pname n = memtbl->look(s,0);
        !           877: 
        !           878:        if (n) {
        !           879:                if (n->tp) {
        !           880:                        switch (n->tp->base) {
        !           881:                        case OVERLOAD:
        !           882:                                break;
        !           883:                        case FCT:
        !           884:                                if (Pfct(n->tp)->f_virtual==0) {
        !           885:                                        if (n->n_dcl_printed==0) n->dcl_print(0);
        !           886:                                        break;
        !           887:                                }
        !           888:                        default:
        !           889:                                  if (c_body==1) dcl_print(0);
        !           890:                        }
        !           891:                }
        !           892: 
        !           893:                if (n->base == PUBLIC) {
        !           894:                        if (mex && n->n_scope==0) {
        !           895:                                if ( is_accessible(n,this) == 0 ) 
        !           896:                                {
        !           897:                                        if ( me == dummy_fct )
        !           898:                                                error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
        !           899:                                        else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
        !           900:                                        mex = 0;        // suppress further error messages
        !           901:                                }
        !           902:                        }
        !           903:                        mex = 0; // don't have find_in_base complain about n
        !           904:                        return find_in_base(s, cl);
        !           905:                }
        !           906: 
        !           907:                if (cl==0 || cl==this) {
        !           908:                        if (mptr==0
        !           909:                        && n->n_stclass!=STATIC
        !           910:                        && n->n_stclass!=ENUM) {
        !           911:                                Ptype t = n->tp;
        !           912: 
        !           913: // error('d',"cl %d this %d",cl,this);
        !           914: 
        !           915:                                if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) {
        !           916:                                        if ( is_accessible(n,this)==0 )
        !           917:                                        {
        !           918:                                                if ( me == dummy_fct )
        !           919:                                                        error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
        !           920:                                                else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
        !           921:                                                mex = 0;        // suppress further error messages
        !           922:                                        }
        !           923:                                }
        !           924: 
        !           925:                                Pname th = cc->c_this;
        !           926:                                Pexpr r = new ref(REF,th,n);
        !           927: 
        !           928:                                if ( access_only == 0 ) {
        !           929:                                        if (th) th->use();
        !           930:                                        n->use();
        !           931:                                }
        !           932:                                r->tp = t;
        !           933:                                return r;
        !           934:                        }
        !           935: 
        !           936:                        if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) {
        !           937:                                if ( is_accessible(n,this)==0 )
        !           938:                                {
        !           939:                                        if ( me == dummy_fct )
        !           940:                                                error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
        !           941:                                        else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
        !           942:                                        mex = 0;        // suppress further error messages
        !           943:                                }
        !           944:                        }
        !           945:                        n->use();
        !           946:                        return n;
        !           947:                }
        !           948:        }
        !           949: 
        !           950:        if ((cl==0 || cl==this) // not qualified to a base class
        !           951:        && csu!=UNION
        !           952:        && csu!=ANON
        !           953:        && strcmp(s,"__as")==0) { // assignment is special: you cannot inherit it
        !           954:                if (baselist==0
        !           955:                || (baselist && baselist->bclass->obj_size!=obj_size)) {
        !           956:                        Pname cn = ktbl->look(string,0);
        !           957:                        if (cn->tp->base == COBJ) cn = Pbase(cn->tp)->b_name;
        !           958:                        Pname x = gtbl->look("__as",0);
        !           959:                        if (x) {        // what if there is an (illegal) global assignment operation?
        !           960:                                        // hack hack don't declare global assignment operations!
        !           961:                                Pfct f = Pfct(x->tp);
        !           962:                                if (f->base == FCT) {
        !           963:                                        Pptr r = f->argtype->tp->is_ref();
        !           964:                                        if (r) {
        !           965:                                                Pname cnn = r->typ->is_cl_obj();
        !           966:                                                if (cnn && cn==cnn) return 0;
        !           967:                                        }
        !           968:                                } else {
        !           969:                                        for (Plist gl = Pgen(f)->fct_list; gl; gl=gl->l) {
        !           970:                                                Pptr r = Pfct(gl->f)->argtype->tp->is_ref();
        !           971:                                                if (r) {
        !           972:                                                        Pname cnn = r->typ->is_cl_obj();
        !           973:                                                        if (cnn &&cn==cnn) return 0;
        !           974:                                                }
        !           975:                                        }
        !           976:                                }
        !           977:                        }
        !           978:                        return make_assignment(cn) ? find_name(s,cl) : 0;
        !           979:                }
        !           980:        }
        !           981: 
        !           982:        return find_in_base(s, cl);
        !           983: }
        !           984: 
        !           985: static Pclass rootClass;
        !           986: static Pbcl pubVClass;
        !           987: static struct PendingMessage { 
        !           988:     Pbcl bc;
        !           989:     Pname mf;
        !           990:     char *nm;
        !           991: } *pM;
        !           992: 
        !           993: Pexpr classdef::find_in_base(char* s, Pclass cl)
        !           994: {
        !           995:        Pbcl bc = 0;
        !           996:        Pexpr e = 0;
        !           997: 
        !           998: // error('d',"%s->find_in_base(%s %s)",string,s,cl?cl->string:"");
        !           999: 
        !          1000:        if ( me == 0 ) mef = 0;
        !          1001:        if (rootClass == 0) rootClass = this;
        !          1002:        for (Pbcl b=baselist; b; b=b->next) {
        !          1003:                Pclass ccl = cl==this?0:cl;
        !          1004: // error('d',"try %t %s %k",b->bclass,b->bclass?b->bclass->string:"?", b->base);
        !          1005:                Pexpr ee = b->bclass->find_name(s,ccl);
        !          1006: 
        !          1007:                if (ee) {
        !          1008:                        if (c_body == 1) {      // look for first use (through this)
        !          1009:                                if (b!=baselist || b->base==VIRTUAL)
        !          1010:                                        dcl_print(0);
        !          1011:                                else {
        !          1012:                                        Pexpr ex = ee;
        !          1013:                                        while ((ex->base==MDOT && ex->i1==1)
        !          1014:                                        || (ex->base==REF && ex->e1==cc->c_this)) ex = ex->mem;
        !          1015:                                        switch (ex->tp->base) {
        !          1016:                                        case OVERLOAD:
        !          1017:                                                break;
        !          1018:                                        case FCT:
        !          1019:                                                if (Pfct(ex->tp)->f_virtual==0) break;
        !          1020:                                        default:
        !          1021:                                                dcl_print(0);
        !          1022:                                        }
        !          1023:                                }
        !          1024:                        }
        !          1025: 
        !          1026:                        if (e) {
        !          1027: // error( 'd', "find_in_base: b( %s ): %k %k ",b->bclass->string,b->base,b->ppp);
        !          1028:                                Pexpr ex = e;
        !          1029:                                int evb = 0;    // number of vbase indirections
        !          1030:                                int eb = 0;
        !          1031: 
        !          1032: // note that this does not catch enum members
        !          1033:                                while (ex->base == MDOT
        !          1034:                                || (ex->base==REF && ex->e1==cc->c_this)) {
        !          1035:                                        if (ex->base==MDOT) evb += int(ex->i1);
        !          1036:                                        ex = ex->mem;
        !          1037:                                }
        !          1038: 
        !          1039:                                Pexpr eex = ee;
        !          1040:                                int eevb = b->base==VIRTUAL;    // number of vbase indirections (incl. possibly this one)
        !          1041:                                int eeb = b->base!=VIRTUAL;
        !          1042: 
        !          1043:                                while (eex->base == MDOT
        !          1044:                                || (eex->base==REF && eex->e1==cc->c_this)) {
        !          1045:                                        if (eex->base==MDOT) eevb += int(eex->i1);
        !          1046:                                        eex = eex->mem;
        !          1047:                                }
        !          1048: 
        !          1049: // error('d', "find_in_base: ex: %k eex: %k, eevb: %d evb: %d", ex->base, eex->base, eevb, evb );
        !          1050: // relying on simple counts for sub-object identification isn't good enough
        !          1051: 
        !          1052:                                if (ex != eex)  {
        !          1053: // error('d',"ex %k tp %k eex %k tp %k", ex->base, ex->tp->base, eex->base, eex->tp->base );
        !          1054:                                //      if (!mqua) {
        !          1055:                                                Pclass ocl, ncl;
        !          1056:                                                if ( ex->tp->base == FCT ) 
        !          1057:                                                        ocl = Pfct(ex->tp)->memof;
        !          1058:                                                else 
        !          1059:                                                if ( ex->tp->base == OVERLOAD )
        !          1060:                                                        ocl = Pfct(Pgen(ex->tp)->fct_list->f->tp)->memof;
        !          1061:                                                else ocl = Pclass(ex->n_table->t_name->tp);
        !          1062: //                                             else ocl = 0;
        !          1063: 
        !          1064:                                                if ( eex->tp->base == FCT ) 
        !          1065:                                                        ncl = Pfct(eex->tp)->memof;
        !          1066:                                                else 
        !          1067:                                                if ( eex->tp->base == OVERLOAD )
        !          1068:                                                        ncl = Pfct(Pgen(eex->tp)->fct_list->f->tp)->memof;
        !          1069:                                                 else ncl = Pclass(eex->n_table->t_name->tp);
        !          1070: //                                             else ncl = 0;
        !          1071: 
        !          1072: //                                             Pclass ocl = Pfct(ex->tp)->memof;
        !          1073: //                                             Pclass ncl = Pfct(eex->tp)->memof;
        !          1074:                                                int eb = ocl?ocl->has_base(ncl):0;
        !          1075:                                                int eeb = ncl?ncl->has_base(ocl):0;
        !          1076: 
        !          1077: //error('d',"eb %d eeb %d evb %d eevb %d",eb,eeb,evb,eevb);
        !          1078:                                                if (eb==0 && eeb==0) {
        !          1079:                                                        // different
        !          1080:                                                        error("ambiguous%n and%n",ex,eex);
        !          1081:                                                        break;
        !          1082:                                                }
        !          1083:                                                else if (eb) {  // ex dominates
        !          1084:                                                        if (eevb<evb) error("ambiguous%n and%n (different sub-objects)",ex,eex);
        !          1085:                                                }
        !          1086:                                                else {  // eex dominates
        !          1087:                                                        e = ee;
        !          1088:                                                        bc = b;
        !          1089:                                                        if (evb<eevb) error("ambiguous%n and%n (different sub-objects)",ex,eex);
        !          1090:                                                }
        !          1091:                                                if (evb==0 && eevb==0) {
        !          1092:                                                        error("ambiguous%n and%n (different sub-objects)",ex,eex);
        !          1093:                                                }
        !          1094:                                //      }
        !          1095:                                //      else {
        !          1096:                                //              // different
        !          1097:                                //              error("ambiguous%n and%n",ex,eex);
        !          1098:                                //              break;
        !          1099:                                //      }
        !          1100:                                }
        !          1101:                                else if (ex->base==NAME
        !          1102:                                && (Pname(ex)->n_evaluated || Pname(ex)->n_sto==EXTERN)) {
        !          1103: //error('d',"enum");
        !          1104:                                }
        !          1105:                                else if (evb==0 && eevb==0) {
        !          1106: //error('d',"e %k",e->base);
        !          1107:                                        // no virtual base => different
        !          1108:                                        error("ambiguous%n and%n (no virtualB)",ex,eex);
        !          1109:                                        break;
        !          1110:                                }
        !          1111:                                else if ((evb && eevb==0) || (eevb && evb==0)) {
        !          1112:                                        // only one virtual base => different
        !          1113:                                        error("ambiguous%n and%n (one not in virtualB)",ex,eex);
        !          1114:                                        break;
        !          1115:                                }
        !          1116:                        }
        !          1117:                        else {
        !          1118:                                e = ee;
        !          1119:                                bc = b;
        !          1120:                        }
        !          1121:                }
        !          1122:        }
        !          1123: 
        !          1124:        if (rootClass == this ) {
        !          1125:                if ( pM ) {
        !          1126:                        // deferred until all base classes of ``this'' examined
        !          1127:                        error("%n cannot access %s: %s is a privateBC",pM->mf,pM->nm,pM->bc->bclass->string);
        !          1128:                        delete pM; pM=0;
        !          1129:                }
        !          1130:                rootClass = 0;
        !          1131:                pubVClass = 0;
        !          1132:        }
        !          1133: 
        !          1134:        if (e == 0) return 0;
        !          1135: 
        !          1136:        if (mex) {
        !          1137:                if ( bc->ppp==PRIVATE ) {       // private base
        !          1138:                        if (this==mec || 
        !          1139:                            (mec && has_friend(mec)) || 
        !          1140:                           (mef && has_friend(mef)))
        !          1141:                                ;
        !          1142:                        else 
        !          1143:                        if ( bc->base == VIRTUAL &&
        !          1144:                             rootClass != this ) { 
        !          1145:                                // if one instance is public, it dominates
        !          1146:                                if ( pubVClass == 0 ||
        !          1147:                                      strcmp(pubVClass->bclass->string,bc->bclass->string)) {
        !          1148:                                        pM = (PendingMessage *) new char[sizeof(*pM)];
        !          1149:                                        pM->bc = bc; pM->mf = me; pM->nm = s;
        !          1150:                                }
        !          1151:                        }
        !          1152:                        else {
        !          1153:                                if ( me == dummy_fct )
        !          1154:                                        error("G scope cannot access %s: %s is a privateBC",s,bc->bclass->string);
        !          1155:                                else error("%n cannot access %s: %s is a privateBC",me,s,bc->bclass->string);
        !          1156:                                mex = 0;
        !          1157:                        }
        !          1158:                }
        !          1159:                else { // public base class
        !          1160:                if ( bc->base == VIRTUAL ) {
        !          1161:                        if ( pM && 
        !          1162:                             strcmp(bc->bclass->string,pM->bc->bclass->string)==0 ) {
        !          1163:                                delete pM;
        !          1164:                                pM=0;
        !          1165:                                pubVClass = bc; 
        !          1166:                                } // previous private member becomes public
        !          1167:                        else pubVClass = bc; // ignore subsequent private instances
        !          1168:                        }
        !          1169:                }
        !          1170:        }
        !          1171: 
        !          1172:        if (e->base==NAME
        !          1173:        && Pname(e)->n_stclass==STATIC) {       // static member
        !          1174:                Pname(e)->use();
        !          1175:                return e;
        !          1176:        }
        !          1177:        if (e->base != NAME)
        !          1178:        if (bc->base == VIRTUAL) {      // this->mem => this->Pbclass->mem
        !          1179:                e->mem = new mdot(bc->bclass->string,e->mem);
        !          1180:                e->mem->i1 = 1;
        !          1181:                e->mem->tp = e->mem->mem->tp;
        !          1182:        }
        !          1183:        else if (bc!=baselist) {        // not first base
        !          1184:                if (e->e1 == cc->c_this) {      // this->mem => this->Obcl.mem
        !          1185:                        e->mem = new mdot(bc->bclass->string,e->mem);
        !          1186:                        e->mem->tp = e->mem->mem->tp;
        !          1187:                }
        !          1188:                else {  // this->p->mem => this->Obcl.p->mem
        !          1189:                        Pexpr ee = e;
        !          1190:                        while (ee->e1->base == REF) ee = ee->e1;
        !          1191:                        ee->mem = new mdot(bc->bclass->string,ee->mem);
        !          1192:                        ee->mem->tp = ee->mem->mem->tp; 
        !          1193:                }
        !          1194:        }
        !          1195: 
        !          1196:        return e;
        !          1197: }
        !          1198: 
        !          1199: int has_virt(Pclass cl)
        !          1200: {
        !          1201:        if (cl->virt_count) return 1;
        !          1202:        for (Pbcl b = cl->baselist; b; b = b->next)
        !          1203:                if (b->bclass->virt_count || has_virt(b->bclass)) return 1;
        !          1204:        return 0;
        !          1205: }
        !          1206: 
        !          1207: Pname find_vptr(Pclass cl)
        !          1208: /*
        !          1209:        find virtual function table
        !          1210:        in memtbl or memtbl of ``first bases''
        !          1211: */
        !          1212: {
        !          1213: //error('d',"find_vptr %t",cl);
        !          1214:        while (cl) {
        !          1215:                Pname vp = cl->memtbl->look("__vptr",0);
        !          1216:                if (vp) return vp;
        !          1217:                Pbcl b = cl->baselist;
        !          1218:                cl = 0;
        !          1219:                for (; b; b = b->next)
        !          1220:                        if (b->base == NAME) {
        !          1221:                                cl = b->bclass;
        !          1222:                                break;
        !          1223:                        }
        !          1224:        }
        !          1225: //error('d',"return 0");
        !          1226:        return 0;
        !          1227: }
        !          1228: 
        !          1229: void make_dummy()
        !          1230: /* a function with no special privileges */
        !          1231: {
        !          1232:         Pname x = new name(".." /*"__static_initializer"*/);
        !          1233:         x->tp = new fct(Pvoid_type,0,1);
        !          1234:         dummy_fct = x->dcl(gtbl,EXTERN);
        !          1235: //     dummy_fct->string = "";
        !          1236:         delete x;
        !          1237: }
        !          1238: 
        !          1239: void check_visibility(Pname n, Pname q, Pclass cl, Ptable tbl, Pname fn)
        !          1240: /*
        !          1241:        "fn" calls "n" a member function of "cl"
        !          1242:        fn can be zero (for functions called in arguments to static constructors) 
        !          1243: */
        !          1244: {
        !          1245: // error('d',"check_visibility(%n, %t, %d, %n)",n,cl,tbl,fn);
        !          1246:        if (fn==0) {
        !          1247:                 if (dummy_fct == 0) make_dummy();
        !          1248:                 fn = dummy_fct;
        !          1249:        }
        !          1250:        Pname nn = new name;
        !          1251:         char* s = n->n_gen_fct_name;    // overloaded name
        !          1252:        nn->string = s?s:n->string;
        !          1253:        nn->n_qualifier = q;
        !          1254:        Pname nx = Pname(find_name(nn,cl,tbl,REF,fn)); // nn deleted by find_name
        !          1255:        if (nx->tp->base != OVERLOAD) return;
        !          1256: 
        !          1257:        // can we get here?
        !          1258: 
        !          1259:        // overloaded not checked by find_name()
        !          1260:        // (since it looks for NAMEs not functions)
        !          1261: 
        !          1262:        for (Plist gl=Pgen(nx->tp)->fct_list; gl; gl=gl->l) {
        !          1263:                Pname nn = gl->f;
        !          1264:                if (n == nn) {
        !          1265:                        if (nn->n_scope) return;        // public member
        !          1266: 
        !          1267:                        Pfct omef = mef;
        !          1268:                        Pclass omec = mec;
        !          1269:                        Pclass otcl = tcl;
        !          1270: 
        !          1271:                        Pclass ncl = Pclass(nn->n_table->t_name->tp);
        !          1272:                        Pname fncn = fn->n_table->t_name;
        !          1273: 
        !          1274:                        mec = fncn?Pclass(fncn->tp):0; 
        !          1275:                        Pfct f = mef = Pfct(fn->tp);
        !          1276:                        tcl = cl;
        !          1277: 
        !          1278:                        int ok = is_accessible( n, ncl, 1 );
        !          1279: 
        !          1280:                        // restore global values
        !          1281:                        mef = omef; mec = omec; tcl = otcl;
        !          1282: 
        !          1283:                        if ( ok ) return;
        !          1284: 
        !          1285:                        if ( Cdcl && Cdcl->base == NAME && 
        !          1286:                                Cdcl->n_stclass == STATIC && 
        !          1287:                                Cdcl->n_initializer && 
        !          1288:                                Cdcl->n_qualifier )
        !          1289:                        {
        !          1290:                                Pbase bn = Pbase(Cdcl->n_qualifier->tp);
        !          1291:                                Pclass ccl = Pclass(bn->b_name->tp);
        !          1292: 
        !          1293:                                if ( ccl == cl || ccl->has_friend(f) ||
        !          1294:                                        (n->n_protect && ccl->has_base(ncl)))
        !          1295:                                                return;
        !          1296:                        }
        !          1297: 
        !          1298:                        if ( fn == dummy_fct )
        !          1299:                                error("G scope cannot access%n: %sM",nn,nn->n_protect?"protected":"private");
        !          1300:                        else error("%n cannot access%n: %sM",fn,nn,nn->n_protect?"protected":"private");
        !          1301:                        return;
        !          1302:                }
        !          1303:        }
        !          1304:        error('i',"visibility check failed");
        !          1305: }

unix.superglobalmegacorp.com

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