|
|
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.