|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.