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