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