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