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