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