Annotation of researchv10no/cmd/cfront/ooptcfront/find.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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